From d9f61821da1d50fc6aad4ba226de1cb58eaab897 Mon Sep 17 00:00:00 2001 From: curiecrypt Date: Wed, 5 Nov 2025 15:39:33 +0300 Subject: [PATCH 1/3] Stm error handling with anyhow --- Cargo.lock | 1 + mithril-aggregator/src/multi_signer.rs | 24 +-- .../cardano/key_certification.rs | 30 ++-- .../src/crypto_helper/codec/binary.rs | 10 +- mithril-common/src/protocol/multi_signer.rs | 23 +-- mithril-common/src/protocol/signer_builder.rs | 12 +- mithril-stm/Cargo.toml | 1 + mithril-stm/README.md | 25 +-- .../src/aggregate_signature/basic_verifier.rs | 32 ++-- mithril-stm/src/aggregate_signature/clerk.rs | 31 ++-- mithril-stm/src/aggregate_signature/mod.rs | 65 ++++---- .../proof/concatenation.rs | 33 ++-- .../src/aggregate_signature/signature.rs | 23 +-- mithril-stm/src/bls_multi_signature/helper.rs | 12 +- mithril-stm/src/bls_multi_signature/mod.rs | 49 ++++-- .../proof_of_possession.rs | 15 +- .../src/bls_multi_signature/signature.rs | 40 ++--- .../src/bls_multi_signature/signing_key.rs | 7 +- .../bls_multi_signature/verification_key.rs | 24 +-- mithril-stm/src/error.rs | 145 ++---------------- mithril-stm/src/key_registration.rs | 28 ++-- mithril-stm/src/lib.rs | 22 ++- mithril-stm/src/merkle_tree/commitment.rs | 51 +++--- mithril-stm/src/merkle_tree/leaf.rs | 6 +- mithril-stm/src/merkle_tree/path.rs | 8 +- mithril-stm/src/merkle_tree/tree.rs | 3 +- mithril-stm/src/participant/initializer.rs | 11 +- mithril-stm/src/single_signature/signature.rs | 37 +++-- .../signature_registered_party.rs | 3 +- mithril-stm/tests/stm_basic.rs | 15 +- mithril-stm/tests/stm_protocol.rs | 25 +-- .../tests/test_extensions/protocol_phase.rs | 6 +- 32 files changed, 418 insertions(+), 399 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 696f28ce1c1..34f052251cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4148,6 +4148,7 @@ dependencies = [ name = "mithril-stm" version = "0.5.5" dependencies = [ + "anyhow", "blake2 0.10.6", "blst", "criterion", diff --git a/mithril-aggregator/src/multi_signer.rs b/mithril-aggregator/src/multi_signer.rs index cac34987ca2..2fba5d8ce20 100644 --- a/mithril-aggregator/src/multi_signer.rs +++ b/mithril-aggregator/src/multi_signer.rs @@ -130,17 +130,19 @@ impl MultiSigner for MultiSignerImpl { self.aggregate_signature_type, ) { Ok(multi_signature) => Ok(Some(multi_signature)), - Err(ProtocolAggregationError::NotEnoughSignatures(actual, expected)) => { - warn!( - self.logger, - "Could not compute multi-signature: Not enough signatures. Got only {actual} out of {expected}." - ); - Ok(None) - } - Err(err) => Err(anyhow!(err).context(format!( - "Multi Signer can not create multi-signature for entity type '{:?}'", - open_message.signed_entity_type - ))), + Err(err) => match err.downcast_ref::() { + Some(ProtocolAggregationError::NotEnoughSignatures(actual, expected)) => { + warn!( + self.logger, + "Could not compute multi-signature: Not enough signatures. Got only {actual} out of {expected}." + ); + Ok(None) + } + _ => Err(anyhow!(err).context(format!( + "Multi Signer can not create multi-signature for entity type '{:?}'", + open_message.signed_entity_type + ))), + }, } } } diff --git a/mithril-common/src/crypto_helper/cardano/key_certification.rs b/mithril-common/src/crypto_helper/cardano/key_certification.rs index 0a6449a78bb..cdaebfec1e2 100644 --- a/mithril-common/src/crypto_helper/cardano/key_certification.rs +++ b/mithril-common/src/crypto_helper/cardano/key_certification.rs @@ -5,6 +5,7 @@ use std::{collections::HashMap, sync::Arc}; +use anyhow::anyhow; use blake2::{ Blake2b, Digest, digest::{FixedOutput, consts::U32}, @@ -173,13 +174,8 @@ impl StmInitializerWrapper { /// * the current total stake (according to the registration service) /// # Error /// This function fails if the initializer is not registered. - pub fn new_signer( - self, - closed_reg: ClosedKeyRegistration, - ) -> Result, ProtocolRegistrationErrorWrapper> { - self.stm_initializer - .create_signer(closed_reg) - .map_err(ProtocolRegistrationErrorWrapper::CoreRegister) + pub fn new_signer(self, closed_reg: ClosedKeyRegistration) -> StdResult> { + self.stm_initializer.create_signer(closed_reg) } /// Convert to bytes @@ -199,7 +195,7 @@ impl StmInitializerWrapper { /// Convert a slice of bytes to an `StmInitializerWrapper` /// # Error /// The function fails if the given string of bytes is not of required size. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StdResult { let stm_initializer = Initializer::from_bytes(bytes.get(..256).ok_or(RegisterError::SerializationError)?)?; let bytes = bytes.get(256..).ok_or(RegisterError::SerializationError)?; @@ -250,7 +246,7 @@ impl KeyRegWrapper { kes_sig: Option, // Used for only for testing when SPO pool id is not certified kes_period: Option, pk: ProtocolSignerVerificationKey, - ) -> Result { + ) -> StdResult { let pool_id_bech32: ProtocolPartyId = if let Some(opcert) = opcert { let signature = kes_sig.ok_or(ProtocolRegistrationErrorWrapper::KesSignatureMissing)?; let kes_period = @@ -264,9 +260,11 @@ impl KeyRegWrapper { .compute_protocol_party_id() .map_err(|_| ProtocolRegistrationErrorWrapper::PoolAddressEncoding)? } else { - return Err(ProtocolRegistrationErrorWrapper::KesSignatureInvalid( - kes_period, - opcert.get_start_kes_period(), + return Err(anyhow!( + ProtocolRegistrationErrorWrapper::KesSignatureInvalid( + kes_period, + opcert.get_start_kes_period(), + ) )); } } else { @@ -277,12 +275,12 @@ impl KeyRegWrapper { }; if let Some(&stake) = self.stake_distribution.get(&pool_id_bech32) { - self.stm_key_reg - .register(stake, pk.into()) - .map_err(ProtocolRegistrationErrorWrapper::CoreRegister)?; + self.stm_key_reg.register(stake, pk.into())?; return Ok(pool_id_bech32); } - Err(ProtocolRegistrationErrorWrapper::PartyIdNonExisting) + Err(anyhow!( + ProtocolRegistrationErrorWrapper::PartyIdNonExisting + )) } /// Finalize the key registration. diff --git a/mithril-common/src/crypto_helper/codec/binary.rs b/mithril-common/src/crypto_helper/codec/binary.rs index 65eb2edc266..7d87eb86321 100644 --- a/mithril-common/src/crypto_helper/codec/binary.rs +++ b/mithril-common/src/crypto_helper/codec/binary.rs @@ -61,7 +61,7 @@ mod binary_mithril_stm { impl TryFromBytes for SingleSignature { fn try_from_bytes(bytes: &[u8]) -> StdResult { - Self::from_bytes::(bytes).map_err(|e| e.into()) + Self::from_bytes::(bytes) } } @@ -73,7 +73,7 @@ mod binary_mithril_stm { impl TryFromBytes for SingleSignatureWithRegisteredParty { fn try_from_bytes(bytes: &[u8]) -> StdResult { - Self::from_bytes::(bytes).map_err(|e| e.into()) + Self::from_bytes::(bytes) } } @@ -97,7 +97,7 @@ mod binary_mithril_stm { impl TryFromBytes for VerificationKey { fn try_from_bytes(bytes: &[u8]) -> StdResult { - Self::from_bytes(bytes).map_err(|e| e.into()) + Self::from_bytes(bytes) } } @@ -109,7 +109,7 @@ mod binary_mithril_stm { impl TryFromBytes for VerificationKeyProofOfPossession { fn try_from_bytes(bytes: &[u8]) -> StdResult { - Self::from_bytes(bytes).map_err(|e| e.into()) + Self::from_bytes(bytes) } } @@ -139,7 +139,7 @@ mod binary_mithril_stm { impl TryFromBytes for Initializer { fn try_from_bytes(bytes: &[u8]) -> StdResult { - Self::from_bytes(bytes).map_err(|e| e.into()) + Self::from_bytes(bytes) } } } diff --git a/mithril-common/src/protocol/multi_signer.rs b/mithril-common/src/protocol/multi_signer.rs index ab629db9f90..b3476640263 100644 --- a/mithril-common/src/protocol/multi_signer.rs +++ b/mithril-common/src/protocol/multi_signer.rs @@ -3,10 +3,7 @@ use mithril_stm::{AggregateSignatureType, Parameters}; use crate::{ StdResult, - crypto_helper::{ - ProtocolAggregateVerificationKey, ProtocolAggregationError, ProtocolClerk, - ProtocolMultiSignature, - }, + crypto_helper::{ProtocolAggregateVerificationKey, ProtocolClerk, ProtocolMultiSignature}, entities::SingleSignature, protocol::ToMessage, }; @@ -31,7 +28,7 @@ impl MultiSigner { single_signatures: &[SingleSignature], message: &T, aggregate_signature_type: AggregateSignatureType, - ) -> Result { + ) -> StdResult { let protocol_signatures: Vec<_> = single_signatures .iter() .map(|single_signature| single_signature.to_protocol_signature()) @@ -94,9 +91,10 @@ impl MultiSigner { #[cfg(test)] mod test { - use mithril_stm::StmSignatureError; + use mithril_stm::MultiSignatureError; use crate::{ + crypto_helper::ProtocolAggregationError, entities::{ProtocolMessage, ProtocolMessagePartKey, ProtocolParameters}, protocol::SignerBuilder, test::{ @@ -129,7 +127,10 @@ mod test { ); assert!( - matches!(error, ProtocolAggregationError::NotEnoughSignatures(_, _)), + matches!( + error.downcast_ref::(), + Some(ProtocolAggregationError::NotEnoughSignatures(_, _)) + ), "Expected ProtocolAggregationError::NotEnoughSignatures, got: {error:?}" ) } @@ -194,8 +195,8 @@ mod test { "Verify single signature should fail if the signer isn't in the registered parties", ); - match error.downcast_ref::() { - Some(StmSignatureError::SignatureInvalid(_)) => (), + match error.downcast_ref::() { + Some(MultiSignatureError::SignatureInvalid(_)) => (), _ => panic!("Expected an SignatureInvalid error, got: {error:?}"), } } @@ -220,8 +221,8 @@ mod test { .verify_single_signature(&ProtocolMessage::default(), &single_signature) .expect_err("Verify single signature should fail"); - match error.downcast_ref::() { - Some(StmSignatureError::SignatureInvalid(_)) => (), + match error.downcast_ref::() { + Some(MultiSignatureError::SignatureInvalid(_)) => (), _ => panic!("Expected an SignatureInvalid error, got: {error:?}"), } } diff --git a/mithril-common/src/protocol/signer_builder.rs b/mithril-common/src/protocol/signer_builder.rs index e6c9c9f448d..c5ca72ecc02 100644 --- a/mithril-common/src/protocol/signer_builder.rs +++ b/mithril-common/src/protocol/signer_builder.rs @@ -177,7 +177,7 @@ mod test { use mithril_stm::RegisterError; use crate::{ - crypto_helper::{KesSignerStandard, ProtocolRegistrationErrorWrapper}, + crypto_helper::KesSignerStandard, test::{builder::MithrilFixtureBuilder, double::fake_data}, }; @@ -220,8 +220,8 @@ mod test { "We should not be able to construct a signer builder if a signer registration fail", ); - match error.downcast_ref::() { - Some(ProtocolRegistrationErrorWrapper::CoreRegister(_)) => (), + match error.downcast_ref::() { + Some(RegisterError::KeyRegistered { .. }) => (), _ => panic!("Expected an CoreRegister error, got: {error:?}"), } } @@ -264,10 +264,8 @@ mod test { "We should not be able to construct a single signer from a not registered party", ); - match error.downcast_ref::() { - Some(ProtocolRegistrationErrorWrapper::CoreRegister( - RegisterError::UnregisteredInitializer, - )) => (), + match error.downcast_ref::() { + Some(RegisterError::UnregisteredInitializer) => (), _ => panic!( "Expected an ProtocolRegistrationErrorWrapper::CoreRegister error, got: {error:?}" ), diff --git a/mithril-stm/Cargo.toml b/mithril-stm/Cargo.toml index 27248eb7503..af54d8f9c3a 100644 --- a/mithril-stm/Cargo.toml +++ b/mithril-stm/Cargo.toml @@ -21,6 +21,7 @@ benchmark-internals = [] # For benchmarking multi_sig future_proof_system = [] # For activating future proof systems [dependencies] +anyhow = { workspace = true } blake2 = "0.10.6" # Enforce blst portable feature for runtime detection of Intel ADX instruction set. blst = { version = "0.3.16", features = ["portable"] } diff --git a/mithril-stm/README.md b/mithril-stm/README.md index 6a9160c524d..cfd232306b5 100644 --- a/mithril-stm/README.md +++ b/mithril-stm/README.md @@ -136,16 +136,21 @@ match msig { println!("Aggregate ok"); assert!(aggr.verify(&msg, &clerk.compute_aggregate_verification_key(), ¶ms).is_ok()); } - Err(AggregationError::NotEnoughSignatures(n, k)) => { - println!("Not enough signatures"); - assert!(n < params.k && k == params.k) - } - Err(AggregationError::UsizeConversionInvalid) => { - println!("Invalid usize conversion"); - } - Err(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { - println!("Unsupported proof system: {:?}", aggregate_signature_type); - } + Err(error) => match error.downcast_ref::() { + Some(AggregationError::NotEnoughSignatures(n, k)) => { + println!("Not enough signatures"); + assert!(n < ¶ms.k && k == ¶ms.k) + }, + Some(AggregationError::UsizeConversionInvalid) => { + println!("Invalid usize conversion"); + }, + Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { + println!("Unsupported proof system: {:?}", aggregate_signature_type); + }, + None => { + println!("Unexpected error during aggregation: {:?}", error); + } + }, } ``` diff --git a/mithril-stm/src/aggregate_signature/basic_verifier.rs b/mithril-stm/src/aggregate_signature/basic_verifier.rs index ab59658650f..9b4fddda80e 100644 --- a/mithril-stm/src/aggregate_signature/basic_verifier.rs +++ b/mithril-stm/src/aggregate_signature/basic_verifier.rs @@ -1,3 +1,4 @@ +use anyhow::{Context, anyhow}; use std::collections::{BTreeMap, HashMap, HashSet}; use crate::bls_multi_signature::{BlsSignature, BlsVerificationKey}; @@ -5,7 +6,7 @@ use crate::key_registration::RegisteredParty; use crate::merkle_tree::MerkleTreeLeaf; use crate::{ AggregationError, CoreVerifierError, Index, Parameters, SingleSignature, - SingleSignatureWithRegisteredParty, Stake, + SingleSignatureWithRegisteredParty, Stake, StmResult, }; /// Full node verifier including the list of eligible signers and the total stake of the system. @@ -56,14 +57,15 @@ impl BasicVerifier { signatures: &[SingleSignatureWithRegisteredParty], parameters: &Parameters, msg: &[u8], - ) -> Result<(), CoreVerifierError> { + ) -> StmResult<()> { let mut nr_indices = 0; let mut unique_indices = HashSet::new(); for sig_reg in signatures { sig_reg .sig - .check_indices(parameters, &sig_reg.reg_party.1, msg, total_stake)?; + .check_indices(parameters, &sig_reg.reg_party.1, msg, total_stake) + .with_context(|| "Preliminary verification for basic verifier failed.")?; for &index in &sig_reg.sig.indexes { unique_indices.insert(index); nr_indices += 1; @@ -71,10 +73,13 @@ impl BasicVerifier { } if nr_indices != unique_indices.len() { - return Err(CoreVerifierError::IndexNotUnique); + return Err(anyhow!(CoreVerifierError::IndexNotUnique)); } if (nr_indices as u64) < parameters.k { - return Err(CoreVerifierError::NoQuorum(nr_indices as u64, parameters.k)); + return Err(anyhow!(CoreVerifierError::NoQuorum( + nr_indices as u64, + parameters.k + ))); } Ok(()) @@ -93,7 +98,7 @@ impl BasicVerifier { params: &Parameters, msg: &[u8], sigs: &[SingleSignatureWithRegisteredParty], - ) -> Result, AggregationError> { + ) -> StmResult> { let mut sig_by_index: BTreeMap = BTreeMap::new(); let mut removal_idx_by_vk: HashMap<&SingleSignatureWithRegisteredParty, Vec> = @@ -169,7 +174,9 @@ impl BasicVerifier { } } } - Err(AggregationError::NotEnoughSignatures(count, params.k)) + Err(anyhow!(AggregationError::NotEnoughSignatures( + count, params.k + ))) } /// Given a slice of `sig_reg_list`, this function returns a new list of `sig_reg_list` with only valid indices. @@ -189,7 +196,7 @@ impl BasicVerifier { params: &Parameters, msg: &[u8], sigs: &[SingleSignatureWithRegisteredParty], - ) -> Result, AggregationError> { + ) -> StmResult> { Self::select_valid_signatures_for_k_indices(total_stake, params, msg, sigs) } @@ -218,7 +225,7 @@ impl BasicVerifier { signatures: &[SingleSignature], parameters: &Parameters, msg: &[u8], - ) -> Result<(), CoreVerifierError> { + ) -> StmResult<()> { let sig_reg_list = signatures .iter() .map(|sig| SingleSignatureWithRegisteredParty { @@ -232,13 +239,16 @@ impl BasicVerifier { parameters, msg, &sig_reg_list, - )?; + ) + .with_context(|| "Basic verification failed during selection of unique k indices.")?; Self::preliminary_verify(&self.total_stake, &unique_sigs, parameters, msg)?; let (sigs, vks) = Self::collect_signatures_verification_keys(&unique_sigs); - BlsSignature::verify_aggregate(msg.to_vec().as_slice(), &vks, &sigs)?; + BlsSignature::verify_aggregate(msg.to_vec().as_slice(), &vks, &sigs).with_context( + || "Basic verifier failed during BLS aggregate signature verification.", + )?; Ok(()) } diff --git a/mithril-stm/src/aggregate_signature/clerk.rs b/mithril-stm/src/aggregate_signature/clerk.rs index 62fe9459587..c540305c4b1 100644 --- a/mithril-stm/src/aggregate_signature/clerk.rs +++ b/mithril-stm/src/aggregate_signature/clerk.rs @@ -1,10 +1,16 @@ -use blake2::digest::{Digest, FixedOutput}; - use crate::{ - AggregateSignature, AggregateSignatureType, AggregateVerificationKey, AggregationError, - ClosedKeyRegistration, Index, Parameters, Signer, SingleSignature, Stake, VerificationKey, + AggregateSignature, AggregateSignatureType, AggregateVerificationKey, ClosedKeyRegistration, + Index, Parameters, Signer, SingleSignature, Stake, StmResult, VerificationKey, aggregate_signature::ConcatenationProof, }; +use anyhow::Context; +use blake2::digest::{Digest, FixedOutput}; + +#[cfg(feature = "future_proof_system")] +use anyhow::anyhow; + +#[cfg(feature = "future_proof_system")] +use crate::AggregationError; /// `Clerk` can verify and aggregate `SingleSignature`s and verify `AggregateSignature`s. /// Clerks can only be generated with the registration closed. @@ -62,7 +68,7 @@ impl Clerk { &self, sigs: &[SingleSignature], msg: &[u8], - ) -> Result, AggregationError> { + ) -> StmResult> { self.aggregate_signatures_with_type(sigs, msg, AggregateSignatureType::default()) } @@ -72,14 +78,19 @@ impl Clerk { sigs: &[SingleSignature], msg: &[u8], aggregate_signature_type: AggregateSignatureType, - ) -> Result, AggregationError> { + ) -> StmResult> { match aggregate_signature_type { AggregateSignatureType::Concatenation => Ok(AggregateSignature::Concatenation( - ConcatenationProof::aggregate_signatures(self, sigs, msg)?, + ConcatenationProof::aggregate_signatures(self, sigs, msg).with_context(|| { + format!( + "Signatures failed to aggregate for type {}", + AggregateSignatureType::Concatenation + ) + })?, )), #[cfg(feature = "future_proof_system")] - AggregateSignatureType::Future => Err(AggregationError::UnsupportedProofSystem( - aggregate_signature_type, + AggregateSignatureType::Future => Err(anyhow!( + AggregationError::UnsupportedProofSystem(aggregate_signature_type) )), } } @@ -96,7 +107,7 @@ impl Clerk { &self, sigs: &[SingleSignature], msg: &[u8], - ) -> Result, AggregationError> { + ) -> StmResult> { Self::aggregate_signatures(self, sigs, msg) } diff --git a/mithril-stm/src/aggregate_signature/mod.rs b/mithril-stm/src/aggregate_signature/mod.rs index 39525a65490..4fb16d81be9 100644 --- a/mithril-stm/src/aggregate_signature/mod.rs +++ b/mithril-stm/src/aggregate_signature/mod.rs @@ -23,12 +23,12 @@ mod tests { use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; - use crate::merkle_tree::MerkleBatchPath; use crate::{ AggregateSignature, AggregateSignatureType, AggregationError, BasicVerifier, Clerk, - CoreVerifierError, Initializer, KeyRegistration, Parameters, Signer, SingleSignature, + Initializer, KeyRegistration, Parameters, Signer, SingleSignature, SingleSignatureWithRegisteredParty, Stake, bls_multi_signature::BlsVerificationKey, }; + use crate::{StmResult, merkle_tree::MerkleBatchPath}; type Sig = AggregateSignature; type D = Blake2b; @@ -147,7 +147,7 @@ mod tests { #[derive(Debug)] struct ProofTest { - msig: Result, + msig: StmResult, clerk: Clerk, msg: [u8; 16], } @@ -259,15 +259,24 @@ mod tests { match msig { Ok(aggr) => { - let verify_result = aggr.verify(&msg, &clerk.compute_aggregate_verification_key(), ¶ms); - assert!(verify_result.is_ok(), "Verification failed: {verify_result:?}"); + println!("Aggregate ok"); + assert!(aggr.verify(&msg, &clerk.compute_aggregate_verification_key(), ¶ms).is_ok()); } - Err(AggregationError::NotEnoughSignatures(n, k)) => - assert!(n < params.k || k == params.k), - Err(AggregationError::UsizeConversionInvalid) => - unreachable!(), - Err(AggregationError::UnsupportedProofSystem(_)) => - unreachable!(), + Err(error) => match error.downcast_ref::() { + Some(AggregationError::NotEnoughSignatures(n, k)) => { + println!("Not enough signatures"); + assert!(n < ¶ms.k && k == ¶ms.k) + }, + Some(AggregationError::UsizeConversionInvalid) => { + println!("Invalid usize conversion"); + }, + Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { + println!("Unsupported proof system: {:?}", aggregate_signature_type); + }, + None => { + println!("Unexpected error during aggregation: {:?}", error); + } + }, } } @@ -303,11 +312,13 @@ mod tests { batch_msgs.push(msg.to_vec()); batch_params.push(params); } - Err(AggregationError::NotEnoughSignatures(_n, _k)) => { - assert!(sigs.len() < params.k as usize) + Err(error) => { assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures{..}) + ), + "Unexpected error: {error:?}"); } - Err(AggregationError::UsizeConversionInvalid) => unreachable!(), - Err(AggregationError::UnsupportedProofSystem(_)) => unreachable!(), } } @@ -428,14 +439,14 @@ mod tests { let clerk = Clerk::new_clerk_from_signer(&ps[0]); let aggr_sig_type = AggregateSignatureType::Concatenation; - let msig = clerk.aggregate_signatures_with_type(&sigs, &msg, aggr_sig_type); - match msig { - Err(AggregationError::NotEnoughSignatures(n, k)) => - assert!(n < params.k && params.k == k), - _ => - unreachable!(), + let error = clerk.aggregate_signatures_with_type(&sigs, &msg, aggr_sig_type).expect_err("Not enough quorum should fail!"); + assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures{..}) + ), + "Unexpected error: {error:?}"); } - } } proptest! { @@ -561,11 +572,13 @@ mod tests { Ok(_) => { assert!(verify_result.is_ok(), "Verification failed: {verify_result:?}"); } - Err(CoreVerifierError::NoQuorum(nr_indices, _k)) => { - assert!((nr_indices) < params.k); + Err(error) => { assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures{..}) + ), + "Unexpected error: {error:?}"); } - Err(CoreVerifierError::IndexNotUnique) => unreachable!(), - _ => unreachable!(), } } diff --git a/mithril-stm/src/aggregate_signature/proof/concatenation.rs b/mithril-stm/src/aggregate_signature/proof/concatenation.rs index bafc5ddac69..0eae91396e6 100644 --- a/mithril-stm/src/aggregate_signature/proof/concatenation.rs +++ b/mithril-stm/src/aggregate_signature/proof/concatenation.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use blake2::digest::{Digest, FixedOutput}; use serde::{Deserialize, Serialize}; @@ -7,8 +8,8 @@ use crate::bls_multi_signature::{BlsSignature, BlsVerificationKey}; use crate::key_registration::RegisteredParty; use crate::merkle_tree::MerkleBatchPath; use crate::{ - AggregateVerificationKey, AggregationError, BasicVerifier, Parameters, SingleSignature, - SingleSignatureWithRegisteredParty, StmAggregateSignatureError, + AggregateVerificationKey, BasicVerifier, Parameters, SingleSignature, + SingleSignatureWithRegisteredParty, StmAggregateSignatureError, StmResult, }; /// `ConcatenationProof` uses the "concatenation" proving system (as described in Section 4.3 of the original paper.) @@ -36,7 +37,7 @@ impl ConcatenationProof { clerk: &Clerk, sigs: &[SingleSignature], msg: &[u8], - ) -> Result, AggregationError> { + ) -> StmResult> { let sig_reg_list = sigs .iter() .map(|sig| SingleSignatureWithRegisteredParty { @@ -52,6 +53,9 @@ impl ConcatenationProof { &clerk.params, &msgp, &sig_reg_list, + ) + .with_context( + || "Failed to aggregate unique signatures during selection for the k indices.", )?; unique_sigs.sort_unstable(); @@ -83,14 +87,15 @@ impl ConcatenationProof { msg: &[u8], avk: &AggregateVerificationKey, parameters: &Parameters, - ) -> Result<(Vec, Vec), StmAggregateSignatureError> { + ) -> StmResult<(Vec, Vec)> { let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg); BasicVerifier::preliminary_verify( &avk.get_total_stake(), &self.signatures, parameters, &msgp, - )?; + ) + .with_context(|| "Preliminary verification of aggregate signatures failed.")?; let leaves = self .signatures @@ -99,7 +104,8 @@ impl ConcatenationProof { .collect::>(); avk.get_merkle_tree_batch_commitment() - .verify_leaves_membership_from_batch_path(&leaves, &self.batch_proof)?; + .verify_leaves_membership_from_batch_path(&leaves, &self.batch_proof) + .with_context(|| "Batch proof is invalid in preliminary verification.")?; Ok(BasicVerifier::collect_signatures_verification_keys( &self.signatures, @@ -117,11 +123,14 @@ impl ConcatenationProof { msg: &[u8], avk: &AggregateVerificationKey, parameters: &Parameters, - ) -> Result<(), StmAggregateSignatureError> { + ) -> StmResult<()> { let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg); - let (sigs, vks) = self.preliminary_verify(msg, avk, parameters)?; + let (sigs, vks) = self + .preliminary_verify(msg, avk, parameters) + .with_context(|| "Aggregate signature verification failed")?; - BlsSignature::verify_aggregate(msgp.as_slice(), &vks, &sigs)?; + BlsSignature::verify_aggregate(msgp.as_slice(), &vks, &sigs) + .with_context(|| "Aggregate signature verification failed")?; Ok(()) } @@ -131,7 +140,7 @@ impl ConcatenationProof { msgs: &[Vec], avks: &[AggregateVerificationKey], parameters: &[Parameters], - ) -> Result<(), StmAggregateSignatureError> { + ) -> StmResult<()> { let batch_size = stm_signatures.len(); assert_eq!( batch_size, @@ -195,9 +204,7 @@ impl ConcatenationProof { } ///Extract a concatenation proof from a byte slice. - pub fn from_bytes( - bytes: &[u8], - ) -> Result, StmAggregateSignatureError> { + pub fn from_bytes(bytes: &[u8]) -> StmResult> { let mut bytes_index = 0; let mut u64_bytes = [0u8; 8]; diff --git a/mithril-stm/src/aggregate_signature/signature.rs b/mithril-stm/src/aggregate_signature/signature.rs index 82d7fa01cda..182de87957c 100644 --- a/mithril-stm/src/aggregate_signature/signature.rs +++ b/mithril-stm/src/aggregate_signature/signature.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use std::collections::HashMap; use std::fmt::Display; use std::hash::Hash; @@ -7,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::error::StmAggregateSignatureError; use crate::merkle_tree::MerkleBatchPath; -use crate::{AggregateVerificationKey, Parameters}; +use crate::{AggregateVerificationKey, Parameters, StmResult}; use super::ConcatenationProof; @@ -95,14 +96,14 @@ impl AggregateSignature { msg: &[u8], avk: &AggregateVerificationKey, parameters: &Parameters, - ) -> Result<(), StmAggregateSignatureError> { + ) -> StmResult<()> { match self { AggregateSignature::Concatenation(concatenation_proof) => { concatenation_proof.verify(msg, avk, parameters) } #[cfg(feature = "future_proof_system")] - AggregateSignature::Future => Err(StmAggregateSignatureError::UnsupportedProofSystem( - self.into(), + AggregateSignature::Future => Err(anyhow!( + StmAggregateSignatureError::UnsupportedProofSystem(self.into()) )), } } @@ -113,7 +114,7 @@ impl AggregateSignature { msgs: &[Vec], avks: &[AggregateVerificationKey], parameters: &[Parameters], - ) -> Result<(), StmAggregateSignatureError> { + ) -> StmResult<()> { let stm_signatures: HashMap> = stm_signatures.iter().fold(HashMap::new(), |mut acc, sig| { acc.entry(sig.into()).or_default().push(sig.clone()); @@ -130,7 +131,7 @@ impl AggregateSignature { .filter_map(|s| s.to_concatenation_proof().cloned()) .collect::>(); if concatenation_proofs.len() != aggregate_signatures_length { - return Err(StmAggregateSignatureError::BatchInvalid); + return Err(anyhow!(StmAggregateSignatureError::BatchInvalid)); } ConcatenationProof::batch_verify( @@ -142,13 +143,13 @@ impl AggregateSignature { } #[cfg(feature = "future_proof_system")] AggregateSignatureType::Future => { - Err(StmAggregateSignatureError::UnsupportedProofSystem( - aggregate_signature_type, - )) + Err(anyhow!(StmAggregateSignatureError::UnsupportedProofSystem( + aggregate_signature_type + ))) } } }) - .map_err(|_| StmAggregateSignatureError::BatchInvalid) + .map_err(|_| anyhow!(StmAggregateSignatureError::BatchInvalid)) } /// Convert an aggregate signature to bytes @@ -171,7 +172,7 @@ impl AggregateSignature { } /// Extract an aggregate signature from a byte slice. - pub fn from_bytes(bytes: &[u8]) -> Result> { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let proof_type_byte = bytes.first().ok_or(StmAggregateSignatureError::SerializationError)?; let proof_bytes = &bytes[1..]; diff --git a/mithril-stm/src/bls_multi_signature/helper.rs b/mithril-stm/src/bls_multi_signature/helper.rs index d2be6e32d16..bdc09056fee 100644 --- a/mithril-stm/src/bls_multi_signature/helper.rs +++ b/mithril-stm/src/bls_multi_signature/helper.rs @@ -1,4 +1,5 @@ pub(crate) mod unsafe_helpers { + use anyhow::anyhow; use blst::{ blst_fp12, blst_fp12_finalverify, blst_p1, blst_p1_affine, blst_p1_affine_generator, blst_p1_compress, blst_p1_from_affine, blst_p1_to_affine, blst_p1_uncompress, blst_p2, @@ -7,8 +8,11 @@ pub(crate) mod unsafe_helpers { min_sig::{PublicKey as BlstVk, SecretKey as BlstSk, Signature as BlstSig}, }; - use crate::bls_multi_signature::{BlsProofOfPossession, BlsVerificationKey}; - use crate::error::{MultiSignatureError, MultiSignatureError::SerializationError}; + use crate::error::MultiSignatureError::SerializationError; + use crate::{ + StmResult, + bls_multi_signature::{BlsProofOfPossession, BlsVerificationKey}, + }; /// Check manually if the pairing `e(g1,mvk) = e(k2,g2)` holds. pub(crate) fn verify_pairing(vk: &BlsVerificationKey, pop: &BlsProofOfPossession) -> bool { @@ -33,7 +37,7 @@ pub(crate) mod unsafe_helpers { bytes } - pub(crate) fn uncompress_p1(bytes: &[u8]) -> Result { + pub(crate) fn uncompress_p1(bytes: &[u8]) -> StmResult { unsafe { if bytes.len() == 48 { let mut point = blst_p1_affine::default(); @@ -42,7 +46,7 @@ pub(crate) mod unsafe_helpers { blst_p1_from_affine(&mut out, &point); Ok(out) } else { - Err(SerializationError) + Err(anyhow!(SerializationError)) } } } diff --git a/mithril-stm/src/bls_multi_signature/mod.rs b/mithril-stm/src/bls_multi_signature/mod.rs index 9f91df30e53..a1fbf2eee68 100644 --- a/mithril-stm/src/bls_multi_signature/mod.rs +++ b/mithril-stm/src/bls_multi_signature/mod.rs @@ -95,7 +95,7 @@ mod tests { use rand_core::{RngCore, SeedableRng}; use crate::bls_multi_signature::helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk}; - use crate::error::{MultiSignatureError, RegisterError}; + use crate::error::MultiSignatureError; use crate::key_registration::KeyRegistration; use super::*; @@ -131,8 +131,14 @@ mod tests { let sk2 = BlsSigningKey::generate(&mut rng); let fake_sig = sk2.sign(&msg); - let result = fake_sig.verify(&msg, &vk1); - assert_eq!(result, Err(MultiSignatureError::SignatureInvalid(fake_sig))); + let error = fake_sig.verify(&msg, &vk1).expect_err("Fake signature should not be verified"); + + assert!( + matches!( + error.downcast_ref::(), + Some(MultiSignatureError::SignatureInvalid(_)) + ), + "Unexpected error: {error:?}"); } #[test] @@ -144,8 +150,13 @@ mod tests { let p1 = blst_p1::default(); let sig_infinity = BlsSignature(p1_affine_to_sig(&p1)); - let result = sig_infinity.verify(&msg, &vk); - assert_eq!(result, Err(MultiSignatureError::SignatureInfinity(sig_infinity))); + let error = sig_infinity.verify(&msg, &vk).expect_err("Verification should fail"); + assert!( + matches!( + error.downcast_ref::(), + Some(MultiSignatureError::SignatureInfinity(_)) + ), + "Unexpected error: {error:?}"); } #[test] @@ -158,8 +169,13 @@ mod tests { let vk_infinity = BlsVerificationKey(p2_affine_to_vk(&p2)); let vkpop_infinity = BlsVerificationKeyProofOfPossession { vk: vk_infinity, pop }; - let result = vkpop_infinity.verify_proof_of_possession(); - assert_eq!(result, Err(MultiSignatureError::VerificationKeyInfinity(Box::new(vkpop_infinity.vk)))); + let error = vkpop_infinity.verify_proof_of_possession().expect_err("VK pop infinity should fail"); + assert!( + matches!( + error.downcast_ref::(), + Some(MultiSignatureError::VerificationKeyInfinity(_)) + ), + "Unexpected error: {error:?}"); } #[test] @@ -179,8 +195,14 @@ mod tests { let _ = kr.register(1, vkpop); } - let result = kr.register(1, vkpop_infinity); - assert_eq!(result, Err(RegisterError::VerificationKeyInfinity(Box::new(vkpop_infinity.vk)))); + let error = kr.register(1, vkpop_infinity).expect_err("VK pop infinity should not be registered"); + + assert!( + matches!( + error.downcast_ref::(), + Some(MultiSignatureError::VerificationKeyInfinity(_)) + ), + "Unexpected error: {error:?}"); } #[test] @@ -272,8 +294,13 @@ mod tests { let fake_sig = sk.sign(&msg); batch_sig[0] = fake_sig; - let batch_result = BlsSignature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig); - assert_eq!(batch_result, Err(MultiSignatureError::BatchInvalid)); + let error = BlsSignature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).expect_err("Batch verify should fail"); + assert!( + matches!( + error.downcast_ref::(), + Some(MultiSignatureError::BatchInvalid) + ), + "Unexpected error: {error:?}"); } } } diff --git a/mithril-stm/src/bls_multi_signature/proof_of_possession.rs b/mithril-stm/src/bls_multi_signature/proof_of_possession.rs index 86f60c7e329..ae645143db2 100644 --- a/mithril-stm/src/bls_multi_signature/proof_of_possession.rs +++ b/mithril-stm/src/bls_multi_signature/proof_of_possession.rs @@ -1,10 +1,13 @@ use blst::{blst_p1, min_sig::Signature as BlstSig}; -use crate::bls_multi_signature::{ - BlsSigningKey, POP, - helper::unsafe_helpers::{compress_p1, scalar_to_pk_in_g1, uncompress_p1}, +use crate::error::{MultiSignatureError, blst_error_to_stm_error}; +use crate::{ + StmResult, + bls_multi_signature::{ + BlsSigningKey, POP, + helper::unsafe_helpers::{compress_p1, scalar_to_pk_in_g1, uncompress_p1}, + }, }; -use crate::error::{MultiSignatureError, blst_err_to_mithril}; /// MultiSig proof of possession, which contains two elements from G1. However, /// the two elements have different types: `k1` is represented as a BlstSig @@ -33,13 +36,13 @@ impl BlsProofOfPossession { } /// Deserialize a byte string to a `PublicKeyPoP`. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let k1 = match BlstSig::from_bytes( bytes.get(..48).ok_or(MultiSignatureError::SerializationError)?, ) { Ok(key) => key, Err(e) => { - return Err(blst_err_to_mithril(e, None, None) + return Err(blst_error_to_stm_error(e, None, None) .expect_err("If it passed, blst returns and error different to SUCCESS.")); } }; diff --git a/mithril-stm/src/bls_multi_signature/signature.rs b/mithril-stm/src/bls_multi_signature/signature.rs index 455af44a8e8..8c428b9da3c 100644 --- a/mithril-stm/src/bls_multi_signature/signature.rs +++ b/mithril-stm/src/bls_multi_signature/signature.rs @@ -1,3 +1,4 @@ +use anyhow::{Context, anyhow}; use std::{cmp::Ordering, iter::Sum}; use blake2::{Blake2b, Blake2b512, Digest}; @@ -8,13 +9,16 @@ use blst::{ }; use digest::consts::U16; -use crate::bls_multi_signature::{ - BlsVerificationKey, - helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk, sig_to_p1, vk_from_p2_affine}, -}; use crate::{ Index, - error::{MultiSignatureError, blst_err_to_mithril}, + error::{MultiSignatureError, blst_error_to_stm_error}, +}; +use crate::{ + StmResult, + bls_multi_signature::{ + BlsVerificationKey, + helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk, sig_to_p1, vk_from_p2_affine}, + }, }; /// MultiSig signature, which is a wrapper over the `BlstSig` type. @@ -23,8 +27,8 @@ pub struct BlsSignature(pub BlstSig); impl BlsSignature { /// Verify a signature against a verification key. - pub fn verify(&self, msg: &[u8], mvk: &BlsVerificationKey) -> Result<(), MultiSignatureError> { - blst_err_to_mithril( + pub fn verify(&self, msg: &[u8], mvk: &BlsVerificationKey) -> StmResult<()> { + blst_error_to_stm_error( self.0.validate(true).map_or_else( |e| e, |_| { @@ -64,11 +68,11 @@ impl BlsSignature { /// /// # Error /// Returns an error if the byte string does not represent a point in the curve. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let bytes = bytes.get(..48).ok_or(MultiSignatureError::SerializationError)?; match BlstSig::sig_validate(bytes, true) { Ok(sig) => Ok(Self(sig)), - Err(e) => Err(blst_err_to_mithril(e, None, None) + Err(e) => Err(blst_error_to_stm_error(e, None, None) .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS.")) } } @@ -96,9 +100,9 @@ impl BlsSignature { pub fn aggregate( vks: &[BlsVerificationKey], sigs: &[BlsSignature], - ) -> Result<(BlsVerificationKey, BlsSignature), MultiSignatureError> { + ) -> StmResult<(BlsVerificationKey, BlsSignature)> { if vks.len() != sigs.len() || vks.is_empty() { - return Err(MultiSignatureError::AggregateSignatureInvalid); + return Err(anyhow!(MultiSignatureError::AggregateSignatureInvalid)); } if vks.len() < 2 { @@ -138,10 +142,10 @@ impl BlsSignature { msg: &[u8], vks: &[BlsVerificationKey], sigs: &[BlsSignature], - ) -> Result<(), MultiSignatureError> { - let (aggr_vk, aggr_sig) = Self::aggregate(vks, sigs)?; + ) -> StmResult<()> { + let (aggr_vk, aggr_sig) = Self::aggregate(vks, sigs).with_context(|| "Multi signature verification failed in aggregation of verification keys and signatures.")?; - blst_err_to_mithril( + blst_error_to_stm_error( aggr_sig.0.verify( false, msg, @@ -160,25 +164,25 @@ impl BlsSignature { msgs: &[Vec], vks: &[BlsVerificationKey], sigs: &[BlsSignature], - ) -> Result<(), MultiSignatureError> { + ) -> StmResult<()> { let batched_sig: BlstSig = match AggregateSignature::aggregate( &(sigs.iter().map(|sig| &sig.0).collect::>()), false, ) { Ok(sig) => BlstSig::from_aggregate(&sig), - Err(e) => return blst_err_to_mithril(e, None, None), + Err(e) => return blst_error_to_stm_error(e, None, None), }; let p2_vks: Vec = vks.iter().map(|vk| vk.to_blst_verification_key()).collect(); let p2_vks_ref: Vec<&BlstVk> = p2_vks.iter().collect(); let slice_msgs = msgs.iter().map(|msg| msg.as_slice()).collect::>(); - blst_err_to_mithril( + blst_error_to_stm_error( batched_sig.aggregate_verify(false, &slice_msgs, &[], &p2_vks_ref, false), None, None, ) - .map_err(|_| MultiSignatureError::BatchInvalid) + .map_err(|_| anyhow!(MultiSignatureError::BatchInvalid)) } } diff --git a/mithril-stm/src/bls_multi_signature/signing_key.rs b/mithril-stm/src/bls_multi_signature/signing_key.rs index 11985c08c7e..d3f0a18d85d 100644 --- a/mithril-stm/src/bls_multi_signature/signing_key.rs +++ b/mithril-stm/src/bls_multi_signature/signing_key.rs @@ -1,8 +1,9 @@ use blst::min_sig::SecretKey as BlstSk; use rand_core::{CryptoRng, RngCore}; +use crate::StmResult; use crate::bls_multi_signature::signature::BlsSignature; -use crate::error::{MultiSignatureError, blst_err_to_mithril}; +use crate::error::{MultiSignatureError, blst_error_to_stm_error}; /// MultiSig secret key, which is a wrapper over the BlstSk type from the blst /// library. @@ -34,11 +35,11 @@ impl BlsSigningKey { /// /// # Error /// Fails if the byte string represents a scalar larger than the group order. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let bytes = bytes.get(..32).ok_or(MultiSignatureError::SerializationError)?; match BlstSk::from_bytes(bytes) { Ok(sk) => Ok(Self(sk)), - Err(e) => Err(blst_err_to_mithril(e, None, None) + Err(e) => Err(blst_error_to_stm_error(e, None, None) .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS.")) } } diff --git a/mithril-stm/src/bls_multi_signature/verification_key.rs b/mithril-stm/src/bls_multi_signature/verification_key.rs index dfbebe2b197..f9e0182d6ce 100644 --- a/mithril-stm/src/bls_multi_signature/verification_key.rs +++ b/mithril-stm/src/bls_multi_signature/verification_key.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use std::{ cmp::Ordering, fmt::{Display, Formatter}, @@ -11,10 +12,13 @@ use blst::{ }; use serde::{Deserialize, Serialize}; -use crate::bls_multi_signature::{ - BlsProofOfPossession, BlsSigningKey, POP, helper::unsafe_helpers::verify_pairing, +use crate::error::{MultiSignatureError, blst_error_to_stm_error}; +use crate::{ + StmResult, + bls_multi_signature::{ + BlsProofOfPossession, BlsSigningKey, POP, helper::unsafe_helpers::verify_pairing, + }, }; -use crate::error::{MultiSignatureError, blst_err_to_mithril}; /// MultiSig verification key, which is a wrapper over the BlstVk (element in G2) /// from the blst library. @@ -32,11 +36,11 @@ impl BlsVerificationKey { /// # Error /// This function fails if the bytes do not represent a compressed point of the prime /// order subgroup of the curve Bls12-381. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let bytes = bytes.get(..96).ok_or(MultiSignatureError::SerializationError)?; match BlstVk::key_validate(bytes) { Ok(vk) => Ok(Self(vk)), - Err(e) => Err(blst_err_to_mithril(e, None, None) + Err(e) => Err(blst_error_to_stm_error(e, None, None) .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS.")) } } @@ -136,7 +140,7 @@ impl BlsVerificationKeyProofOfPossession { /// manually. // If we are really looking for performance improvements, we can combine the // two final exponentiations (for verifying k1 and k2) into a single one. - pub(crate) fn verify_proof_of_possession(&self) -> Result<(), MultiSignatureError> { + pub(crate) fn verify_proof_of_possession(&self) -> StmResult<()> { match self.vk.to_blst_verification_key().validate() { Ok(_) => { let result = verify_pairing(&self.vk, &self.pop); @@ -150,11 +154,11 @@ impl BlsVerificationKeyProofOfPossession { ) == BLST_ERROR::BLST_SUCCESS && result) { - return Err(MultiSignatureError::KeyInvalid(Box::new(*self))); + return Err(anyhow!(MultiSignatureError::KeyInvalid(Box::new(*self)))); } Ok(()) } - Err(e) => blst_err_to_mithril(e, None, Some(self.vk)), + Err(e) => blst_error_to_stm_error(e, None, Some(self.vk)), } } @@ -168,7 +172,7 @@ impl BlsVerificationKeyProofOfPossession { since = "0.5.0", note = "The verification of the proof of possession is not part of the public API any more" )] - pub fn check(&self) -> Result<(), MultiSignatureError> { + pub fn check(&self) -> StmResult<()> { Self::verify_proof_of_possession(self) } @@ -186,7 +190,7 @@ impl BlsVerificationKeyProofOfPossession { } /// Deserialize a byte string to a `BlsVerificationKeyProofOfPossession`. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let mvk = BlsVerificationKey::from_bytes( bytes.get(..96).ok_or(MultiSignatureError::SerializationError)?, )?; diff --git a/mithril-stm/src/error.rs b/mithril-stm/src/error.rs index c56f2e29c7b..6a52dac23c5 100644 --- a/mithril-stm/src/error.rs +++ b/mithril-stm/src/error.rs @@ -1,12 +1,12 @@ //! Crate specific errors -use blake2::digest::{Digest, FixedOutput}; +use anyhow::anyhow; use blst::BLST_ERROR; +use crate::StmResult; use crate::aggregate_signature::AggregateSignatureType; use crate::bls_multi_signature::{ BlsSignature, BlsVerificationKey, BlsVerificationKeyProofOfPossession, }; -use crate::merkle_tree::{MerkleBatchPath, MerklePath}; /// Error types for multi signatures. #[derive(Debug, thiserror::Error, Eq, PartialEq)] @@ -42,18 +42,18 @@ pub enum MultiSignatureError { /// Error types related to merkle trees. #[derive(Debug, Clone, thiserror::Error)] -pub enum MerkleTreeError { +pub enum MerkleTreeError { /// Serialization error #[error("Serialization of a merkle tree failed")] SerializationError, /// Invalid merkle path #[error("Path does not verify against root")] - PathInvalid(MerklePath), + PathInvalid(Vec), /// Invalid merkle batch path #[error("Batch path does not verify against root")] - BatchPathInvalid(MerkleBatchPath), + BatchPathInvalid(Vec), } /// Errors which can be output by Mithril single signature verification. @@ -84,29 +84,6 @@ pub enum StmSignatureError { SerializationError, } -impl From for StmSignatureError { - fn from(e: MultiSignatureError) -> Self { - match e { - MultiSignatureError::SerializationError => Self::SerializationError, - MultiSignatureError::SignatureInvalid(e) => Self::SignatureInvalid(e), - MultiSignatureError::BatchInvalid => unreachable!(), - MultiSignatureError::KeyInvalid(_) => unreachable!(), - MultiSignatureError::AggregateSignatureInvalid => unreachable!(), - MultiSignatureError::SignatureInfinity(_) => unreachable!(), - MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(), - } - } -} - -impl From> for StmSignatureError { - fn from(e: MerkleTreeError) -> Self { - match e { - MerkleTreeError::SerializationError => Self::SerializationError, - _ => unreachable!(), - } - } -} - /// Error types for aggregation. #[derive(Debug, Clone, thiserror::Error)] pub enum AggregationError { @@ -143,39 +120,9 @@ pub enum CoreVerifierError { IndividualSignatureInvalid(#[source] StmSignatureError), } -impl From for CoreVerifierError { - fn from(e: AggregationError) -> Self { - match e { - AggregationError::NotEnoughSignatures(e, _e) => Self::NoQuorum(e, e), - AggregationError::UsizeConversionInvalid => unreachable!(), - AggregationError::UnsupportedProofSystem(_) => unreachable!(), - } - } -} - -impl From for CoreVerifierError { - fn from(e: MultiSignatureError) -> Self { - match e { - MultiSignatureError::AggregateSignatureInvalid => Self::AggregateSignatureInvalid, - MultiSignatureError::BatchInvalid => unreachable!(), - MultiSignatureError::SerializationError => unreachable!(), - MultiSignatureError::KeyInvalid(_) => unreachable!(), - MultiSignatureError::SignatureInvalid(_e) => unreachable!(), - MultiSignatureError::SignatureInfinity(_) => unreachable!(), - MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(), - } - } -} - -impl From for CoreVerifierError { - fn from(e: StmSignatureError) -> Self { - CoreVerifierError::IndividualSignatureInvalid(e) - } -} - /// Errors which can be output by Mithril aggregate verification. #[derive(Debug, Clone, thiserror::Error)] -pub enum StmAggregateSignatureError { +pub enum StmAggregateSignatureError { /// The IVK is invalid after aggregating the keys #[error("Aggregated key does not correspond to the expected key.")] IvkInvalid(Box), @@ -186,7 +133,7 @@ pub enum StmAggregateSignatureError { /// Invalid merkle batch path #[error("Batch path does not verify against root")] - PathInvalid(MerkleBatchPath), + PathInvalid(Vec), /// Batch verification of STM aggregate signatures failed #[error("Batch verification of STM aggregate signatures failed")] @@ -201,53 +148,6 @@ pub enum StmAggregateSignatureError { UnsupportedProofSystem(AggregateSignatureType), } -impl From> for StmAggregateSignatureError { - fn from(e: MerkleTreeError) -> Self { - match e { - MerkleTreeError::BatchPathInvalid(e) => Self::PathInvalid(e), - MerkleTreeError::SerializationError => Self::SerializationError, - MerkleTreeError::PathInvalid(_e) => unreachable!(), - } - } -} - -impl From for StmAggregateSignatureError { - fn from(e: MultiSignatureError) -> Self { - match e { - MultiSignatureError::AggregateSignatureInvalid => { - Self::from(CoreVerifierError::from(e)) - } - MultiSignatureError::BatchInvalid => Self::BatchInvalid, - MultiSignatureError::SerializationError => unreachable!(), - MultiSignatureError::KeyInvalid(_) => unreachable!(), - MultiSignatureError::SignatureInvalid(_) => { - Self::CoreVerificationError(CoreVerifierError::from(e)) - } - MultiSignatureError::SignatureInfinity(_) => { - Self::CoreVerificationError(CoreVerifierError::from(e)) - } - MultiSignatureError::VerificationKeyInfinity(_) => { - Self::CoreVerificationError(CoreVerifierError::from(e)) - } - } - } -} - -impl From for StmAggregateSignatureError { - fn from(e: CoreVerifierError) -> Self { - Self::CoreVerificationError(e) - } -} - -impl From for StmAggregateSignatureError { - fn from(e: StmSignatureError) -> Self { - match e { - StmSignatureError::SerializationError => Self::SerializationError, - _ => unreachable!(), - } - } -} - /// Errors which can be outputted by key registration. #[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)] pub enum RegisterError { @@ -272,42 +172,31 @@ pub enum RegisterError { UnregisteredInitializer, } -impl From for RegisterError { - fn from(e: MultiSignatureError) -> Self { - match e { - MultiSignatureError::SerializationError => Self::SerializationError, - MultiSignatureError::KeyInvalid(e) => Self::KeyInvalid(e), - MultiSignatureError::VerificationKeyInfinity(e) => Self::VerificationKeyInfinity(e), - _ => unreachable!(), - } - } -} - -/// If verifying a single signature, the signature should be provided. If verifying a multi-sig, -/// no need to provide the signature -pub(crate) fn blst_err_to_mithril( +pub(crate) fn blst_error_to_stm_error( e: BLST_ERROR, sig: Option, key: Option, -) -> Result<(), MultiSignatureError> { +) -> StmResult<()> { match e { BLST_ERROR::BLST_SUCCESS => Ok(()), BLST_ERROR::BLST_PK_IS_INFINITY => { if let Some(s) = sig { - return Err(MultiSignatureError::SignatureInfinity(s)); + return Err(anyhow!(MultiSignatureError::SignatureInfinity(s))); } if let Some(vk) = key { - return Err(MultiSignatureError::VerificationKeyInfinity(Box::new(vk))); + return Err(anyhow!(MultiSignatureError::VerificationKeyInfinity( + Box::new(vk) + ))); } - Err(MultiSignatureError::SerializationError) + Err(anyhow!(MultiSignatureError::SerializationError)) } BLST_ERROR::BLST_VERIFY_FAIL => { if let Some(s) = sig { - Err(MultiSignatureError::SignatureInvalid(s)) + Err(anyhow!(MultiSignatureError::SignatureInvalid(s))) } else { - Err(MultiSignatureError::AggregateSignatureInvalid) + Err(anyhow!(MultiSignatureError::AggregateSignatureInvalid)) } } - _ => Err(MultiSignatureError::SerializationError), + _ => Err(anyhow!(MultiSignatureError::SerializationError)), } } diff --git a/mithril-stm/src/key_registration.rs b/mithril-stm/src/key_registration.rs index 839ea005267..feb06bd5954 100644 --- a/mithril-stm/src/key_registration.rs +++ b/mithril-stm/src/key_registration.rs @@ -4,12 +4,13 @@ use std::{ sync::Arc, }; +use anyhow::anyhow; use blake2::digest::{Digest, FixedOutput}; -use crate::Stake; use crate::bls_multi_signature::{BlsVerificationKey, BlsVerificationKeyProofOfPossession}; use crate::error::RegisterError; use crate::merkle_tree::{MerkleTree, MerkleTreeLeaf}; +use crate::{Stake, StmResult}; /// Stores a registered party with its public key and the associated stake. pub type RegisteredParty = MerkleTreeLeaf; @@ -35,13 +36,13 @@ impl KeyRegistration { &mut self, stake: Stake, pk: BlsVerificationKeyProofOfPossession, - ) -> Result<(), RegisterError> { + ) -> StmResult<()> { if let Entry::Vacant(e) = self.keys.entry(pk.vk) { pk.verify_proof_of_possession()?; e.insert(stake); return Ok(()); } - Err(RegisterError::KeyRegistered(Box::new(pk.vk))) + Err(anyhow!(RegisterError::KeyRegistered(Box::new(pk.vk)))) } /// Finalize the key registration. @@ -126,23 +127,24 @@ mod tests { } let reg = kr.register(stake, pk); + match reg { Ok(_) => { assert!(keys.insert(pk.vk, stake).is_none()); }, - Err(RegisterError::KeyRegistered(pk1)) => { - assert!(pk1.as_ref() == &pk.vk); - assert!(keys.contains_key(&pk.vk)); - } - Err(RegisterError::KeyInvalid(a)) => { - assert_eq!(fake_it, 0); - assert!(a.verify_proof_of_possession().is_err()); + Err(error) => match error.downcast_ref::(){ + Some(RegisterError::KeyRegistered(pk1)) => { + assert!(pk1.as_ref() == &pk.vk); + assert!(keys.contains_key(&pk.vk)); + }, + Some(RegisterError::KeyInvalid(a)) => { + assert_eq!(fake_it, 0); + assert!(a.verify_proof_of_possession().is_err()); + }, + _ => {println!("Unexpected error: {error}")} } - Err(RegisterError::SerializationError) => unreachable!(), - _ => unreachable!(), } } - if !kr.keys.is_empty() { let closed = kr.close::>(); let retrieved_keys = closed.reg_parties.iter().map(|r| (r.0, r.1)).collect::>(); diff --git a/mithril-stm/src/lib.rs b/mithril-stm/src/lib.rs index 2ca7313521b..fb5212649d3 100644 --- a/mithril-stm/src/lib.rs +++ b/mithril-stm/src/lib.rs @@ -99,11 +99,13 @@ //! .verify(&msg, &clerk.compute_avk(), ¶ms) //! .is_ok()); //! } -//! Err(AggregationError::NotEnoughSignatures(n, k)) => { -//! println!("Not enough signatures"); -//! assert!(n < params.k && k == params.k) -//! } -//! Err(_) => unreachable!(), +//! Err(error) => assert!( +//! matches!( +//! error.downcast_ref::(), +//! Some(AggregationError::NotEnoughSignatures { .. }) +//! ), +//! "Unexpected error: {error}" +//! ), //! } //! # Ok(()) //! # } @@ -123,8 +125,8 @@ pub use aggregate_signature::{ AggregateSignature, AggregateSignatureType, AggregateVerificationKey, BasicVerifier, Clerk, }; pub use error::{ - AggregationError, CoreVerifierError, RegisterError, StmAggregateSignatureError, - StmSignatureError, + AggregationError, CoreVerifierError, MultiSignatureError, RegisterError, + StmAggregateSignatureError, StmSignatureError, }; pub use key_registration::{ClosedKeyRegistration, KeyRegistration}; pub use parameters::Parameters; @@ -144,6 +146,12 @@ pub type Stake = u64; /// An aggregate signature (`StmMultiSig`) must have at least `k` unique indices. pub type Index = u64; +/// Mithril-stm error type +pub type StmError = anyhow::Error; + +/// Mithril-stm result type +pub type StmResult = anyhow::Result; + // Aliases #[deprecated(since = "0.5.0", note = "Use `AggregateSignature` instead")] pub use aggregate_signature::AggregateSignature as StmAggrSig; diff --git a/mithril-stm/src/merkle_tree/commitment.rs b/mithril-stm/src/merkle_tree/commitment.rs index d54873fc33f..131a02c8ebb 100644 --- a/mithril-stm/src/merkle_tree/commitment.rs +++ b/mithril-stm/src/merkle_tree/commitment.rs @@ -3,9 +3,10 @@ use std::marker::PhantomData; use blake2::digest::{Digest, FixedOutput}; use serde::{Deserialize, Serialize}; +use crate::StmResult; use crate::error::MerkleTreeError; use crate::merkle_tree::{MerkleBatchPath, MerklePath, MerkleTreeLeaf, parent, sibling}; - +use anyhow::{Context, anyhow}; /// `MerkleTree` commitment. /// This structure differs from `MerkleTree` in that it does not contain all elements, which are not always necessary. /// Instead, it only contains the root of the tree. @@ -31,7 +32,7 @@ impl MerkleTreeCommitment { &self, val: &MerkleTreeLeaf, proof: &MerklePath, - ) -> Result<(), MerkleTreeError> + ) -> StmResult<()> where D: FixedOutput + Clone, { @@ -50,7 +51,7 @@ impl MerkleTreeCommitment { if h == self.root { return Ok(()); } - Err(MerkleTreeError::PathInvalid(proof.clone())) + Err(anyhow!(MerkleTreeError::PathInvalid(proof.to_bytes()))) } /// Check an inclusion proof that `val` is part of the tree by traveling the whole path until the root. @@ -60,11 +61,7 @@ impl MerkleTreeCommitment { since = "0.5.0", note = "Use `verify_leaf_membership_from_path` instead" )] - pub fn check( - &self, - val: &MerkleTreeLeaf, - proof: &MerklePath, - ) -> Result<(), MerkleTreeError> + pub fn check(&self, val: &MerkleTreeLeaf, proof: &MerklePath) -> StmResult<()> where D: FixedOutput + Clone, { @@ -104,7 +101,7 @@ impl MerkleTreeCommitment { } /// Extract a `MerkleTreeCommitment` from a byte slice. - pub fn from_bytes(bytes: &[u8]) -> Result, MerkleTreeError> { + pub fn from_bytes(bytes: &[u8]) -> StmResult> { let root = bytes.to_vec(); Ok(Self { @@ -171,18 +168,18 @@ impl MerkleTreeBatchCommitment { &self, batch_val: &[MerkleTreeLeaf], proof: &MerkleBatchPath, - ) -> Result<(), MerkleTreeError> + ) -> StmResult<()> where D: FixedOutput + Clone, { if batch_val.len() != proof.indices.len() { - return Err(MerkleTreeError::BatchPathInvalid(proof.clone())); + return Err(anyhow!(MerkleTreeError::BatchPathInvalid(proof.to_bytes()))); } let mut ordered_indices: Vec = proof.indices.clone(); ordered_indices.sort_unstable(); if ordered_indices != proof.indices { - return Err(MerkleTreeError::BatchPathInvalid(proof.clone())); + return Err(anyhow!(MerkleTreeError::BatchPathInvalid(proof.to_bytes()))); } let nr_nodes = self.nr_leaves + self.nr_leaves.next_power_of_two() - 1; @@ -211,7 +208,14 @@ impl MerkleTreeBatchCommitment { if ordered_indices[i] & 1 == 0 { new_hashes.push( D::new() - .chain(values.first().ok_or(MerkleTreeError::SerializationError)?) + .chain( + values + .first() + .ok_or(MerkleTreeError::SerializationError) + .with_context(|| { + format!("Could not verify leave membership from batch path for idx = {} and ordered_indices[{}]", idx, i) + })?, + ) .chain(&leaves[i]) .finalize() .to_vec(), @@ -228,7 +232,16 @@ impl MerkleTreeBatchCommitment { new_hashes.push( D::new() .chain(&leaves[i]) - .chain(values.first().ok_or(MerkleTreeError::SerializationError)?) + .chain( + values + .first() + .ok_or(MerkleTreeError::SerializationError) + .with_context(|| { + format!( + "Could not verify leave membership from batch path for idx = {} where sibling < nr_nodes", idx + ) + })?, + ) .finalize() .to_vec(), ); @@ -249,7 +262,7 @@ impl MerkleTreeBatchCommitment { return Ok(()); } - Err(MerkleTreeError::BatchPathInvalid(proof.clone())) + Err(anyhow!(MerkleTreeError::BatchPathInvalid(proof.to_bytes()))) } /// Check a proof of a batched opening. The indices must be ordered. @@ -263,11 +276,7 @@ impl MerkleTreeBatchCommitment { since = "0.5.0", note = "Use `verify_leaves_membership_from_batch_path` instead" )] - pub fn check( - &self, - batch_val: &[MerkleTreeLeaf], - proof: &MerkleBatchPath, - ) -> Result<(), MerkleTreeError> + pub fn check(&self, batch_val: &[MerkleTreeLeaf], proof: &MerkleBatchPath) -> StmResult<()> where D: FixedOutput + Clone, { @@ -286,7 +295,7 @@ impl MerkleTreeBatchCommitment { } /// Extract a `MerkleTreeBatchCommitment` from a byte slice. - pub fn from_bytes(bytes: &[u8]) -> Result, MerkleTreeError> { + pub fn from_bytes(bytes: &[u8]) -> StmResult> { let mut u64_bytes = [0u8; 8]; u64_bytes.copy_from_slice(bytes.get(..8).ok_or(MerkleTreeError::SerializationError)?); let nr_leaves = usize::try_from(u64::from_be_bytes(u64_bytes)) diff --git a/mithril-stm/src/merkle_tree/leaf.rs b/mithril-stm/src/merkle_tree/leaf.rs index 675bfb77bf5..de01655d850 100644 --- a/mithril-stm/src/merkle_tree/leaf.rs +++ b/mithril-stm/src/merkle_tree/leaf.rs @@ -1,20 +1,18 @@ use std::cmp::Ordering; -use blake2::Blake2b; -use digest::consts::U32; use serde::{Deserialize, Serialize}; +use crate::StmResult; use crate::bls_multi_signature::BlsVerificationKey; use crate::error::MerkleTreeError; use crate::{Stake, VerificationKey}; - /// The values that are committed in the Merkle Tree. /// Namely, a verified `VerificationKey` and its corresponding stake. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, Hash)] pub struct MerkleTreeLeaf(pub BlsVerificationKey, pub Stake); impl MerkleTreeLeaf { - pub(crate) fn from_bytes(bytes: &[u8]) -> Result>> { + pub(crate) fn from_bytes(bytes: &[u8]) -> StmResult { let pk = VerificationKey::from_bytes(bytes).map_err(|_| MerkleTreeError::SerializationError)?; let mut u64_bytes = [0u8; 8]; diff --git a/mithril-stm/src/merkle_tree/path.rs b/mithril-stm/src/merkle_tree/path.rs index 565de41692a..5ba011bffa0 100644 --- a/mithril-stm/src/merkle_tree/path.rs +++ b/mithril-stm/src/merkle_tree/path.rs @@ -1,10 +1,10 @@ use std::marker::PhantomData; +use crate::StmResult; +use crate::error::MerkleTreeError; use blake2::digest::{Digest, FixedOutput}; use serde::{Deserialize, Serialize}; -use crate::error::MerkleTreeError; - /// Path of hashes from root to leaf in a Merkle Tree. /// Contains all hashes on the path, and the index of the leaf. /// Used to verify that signatures come from eligible signers. @@ -43,7 +43,7 @@ impl MerklePath { /// Extract a `Path` from a byte slice. /// # Error /// This function fails if the bytes cannot retrieve path. - pub fn from_bytes(bytes: &[u8]) -> Result, MerkleTreeError> { + pub fn from_bytes(bytes: &[u8]) -> StmResult> { let mut u64_bytes = [0u8; 8]; u64_bytes.copy_from_slice(bytes.get(..8).ok_or(MerkleTreeError::SerializationError)?); let index = usize::try_from(u64::from_be_bytes(u64_bytes)) @@ -118,7 +118,7 @@ impl MerkleBatchPath { } /// Try to convert a byte string into a `BatchPath`. - pub fn from_bytes(bytes: &[u8]) -> Result> { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let mut u64_bytes = [0u8; 8]; u64_bytes.copy_from_slice(&bytes[..8]); let len_v = usize::try_from(u64::from_be_bytes(u64_bytes)) diff --git a/mithril-stm/src/merkle_tree/tree.rs b/mithril-stm/src/merkle_tree/tree.rs index 3fae57f6d71..68c947f1504 100644 --- a/mithril-stm/src/merkle_tree/tree.rs +++ b/mithril-stm/src/merkle_tree/tree.rs @@ -3,6 +3,7 @@ use std::marker::PhantomData; use blake2::digest::{Digest, FixedOutput}; use serde::{Deserialize, Serialize}; +use crate::StmResult; use crate::error::MerkleTreeError; use crate::merkle_tree::{ MerkleBatchPath, MerklePath, MerkleTreeBatchCommitment, MerkleTreeCommitment, MerkleTreeLeaf, @@ -194,7 +195,7 @@ impl MerkleTree { /// Try to convert a byte string into a `MerkleTree`. /// # Error /// It returns error if conversion fails. - pub fn from_bytes(bytes: &[u8]) -> Result> { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let mut u64_bytes = [0u8; 8]; u64_bytes.copy_from_slice(bytes.get(..8).ok_or(MerkleTreeError::SerializationError)?); let n = usize::try_from(u64::from_be_bytes(u64_bytes)) diff --git a/mithril-stm/src/participant/initializer.rs b/mithril-stm/src/participant/initializer.rs index 63e428511c5..5471e25adfb 100644 --- a/mithril-stm/src/participant/initializer.rs +++ b/mithril-stm/src/participant/initializer.rs @@ -4,8 +4,9 @@ use rand_core::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use crate::bls_multi_signature::{BlsSigningKey, BlsVerificationKeyProofOfPossession}; -use crate::key_registration::*; use crate::{Parameters, RegisterError, Signer, Stake}; +use crate::{StmResult, key_registration::*}; +use anyhow::anyhow; /// Wrapper of the MultiSignature Verification key with proof of possession pub type VerificationKeyProofOfPossession = BlsVerificationKeyProofOfPossession; @@ -75,7 +76,7 @@ impl Initializer { pub fn create_signer( self, closed_reg: ClosedKeyRegistration, - ) -> Result, RegisterError> { + ) -> StmResult> { let mut my_index = None; for (i, rp) in closed_reg.reg_parties.iter().enumerate() { if rp.0 == self.pk.vk { @@ -84,7 +85,7 @@ impl Initializer { } } if my_index.is_none() { - return Err(RegisterError::UnregisteredInitializer); + return Err(anyhow!(RegisterError::UnregisteredInitializer)); } Ok(Signer::set_signer( @@ -113,7 +114,7 @@ impl Initializer { pub fn new_signer( self, closed_reg: ClosedKeyRegistration, - ) -> Result, RegisterError> { + ) -> StmResult> { Self::create_signer(self, closed_reg) } @@ -177,7 +178,7 @@ impl Initializer { /// Convert a slice of bytes to an `Initializer` /// # Error /// The function fails if the given string of bytes is not of required size. - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let mut u64_bytes = [0u8; 8]; u64_bytes.copy_from_slice(bytes.get(..8).ok_or(RegisterError::SerializationError)?); let stake = u64::from_be_bytes(u64_bytes); diff --git a/mithril-stm/src/single_signature/signature.rs b/mithril-stm/src/single_signature/signature.rs index 4094998f369..1f031cede4a 100644 --- a/mithril-stm/src/single_signature/signature.rs +++ b/mithril-stm/src/single_signature/signature.rs @@ -9,8 +9,10 @@ use serde::{Deserialize, Serialize}; use crate::bls_multi_signature::BlsSignature; use crate::eligibility_check::is_lottery_won; use crate::{ - AggregateVerificationKey, Index, Parameters, Stake, StmSignatureError, VerificationKey, + AggregateVerificationKey, Index, Parameters, Stake, StmResult, StmSignatureError, + VerificationKey, }; +use anyhow::{Context, anyhow}; /// Signature created by a single party who has won the lottery. #[derive(Debug, Clone, Serialize, Deserialize)] @@ -33,9 +35,15 @@ impl SingleSignature { stake: &Stake, avk: &AggregateVerificationKey, msg: &[u8], - ) -> Result<(), StmSignatureError> { + ) -> StmResult<()> { let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg); - self.basic_verify(params, pk, stake, &msgp, &avk.get_total_stake())?; + self.basic_verify(params, pk, stake, &msgp, &avk.get_total_stake()) + .with_context(|| { + format!( + "Single signature verification failed for signer index {}.", + self.signer_index + ) + })?; Ok(()) } @@ -46,16 +54,18 @@ impl SingleSignature { stake: &Stake, msg: &[u8], total_stake: &Stake, - ) -> Result<(), StmSignatureError> { + ) -> StmResult<()> { for &index in &self.indexes { if index > params.m { - return Err(StmSignatureError::IndexBoundFailed(index, params.m)); + return Err(anyhow!(StmSignatureError::IndexBoundFailed( + index, params.m + ))); } let ev = self.sigma.evaluate_dense_mapping(msg, index); if !is_lottery_won(params.phi_f, ev, *stake, *total_stake) { - return Err(StmSignatureError::LotteryLost); + return Err(anyhow!(StmSignatureError::LotteryLost)); } } @@ -86,9 +96,7 @@ impl SingleSignature { } /// Extract a batch compatible `SingleSignature` from a byte slice. - pub fn from_bytes( - bytes: &[u8], - ) -> Result { + pub fn from_bytes(bytes: &[u8]) -> StmResult { let mut u64_bytes = [0u8; 8]; u64_bytes.copy_from_slice(bytes.get(0..8).ok_or(StmSignatureError::SerializationError)?); @@ -145,9 +153,12 @@ impl SingleSignature { stake: &Stake, msg: &[u8], total_stake: &Stake, - ) -> Result<(), StmSignatureError> { - self.sigma.verify(msg, pk)?; - self.check_indices(params, stake, msg, total_stake)?; + ) -> StmResult<()> { + self.sigma + .verify(msg, pk) + .with_context(|| "Basic verification of single signature failed.")?; + self.check_indices(params, stake, msg, total_stake) + .with_context(|| "Basic verification of single signature failed.")?; Ok(()) } @@ -161,7 +172,7 @@ impl SingleSignature { stake: &Stake, msg: &[u8], total_stake: &Stake, - ) -> Result<(), StmSignatureError> { + ) -> StmResult<()> { Self::basic_verify(self, params, pk, stake, msg, total_stake) } } diff --git a/mithril-stm/src/single_signature/signature_registered_party.rs b/mithril-stm/src/single_signature/signature_registered_party.rs index 80169a12e1e..23c176e2a13 100644 --- a/mithril-stm/src/single_signature/signature_registered_party.rs +++ b/mithril-stm/src/single_signature/signature_registered_party.rs @@ -1,6 +1,7 @@ use blake2::digest::{Digest, FixedOutput}; use serde::{Deserialize, Serialize, Serializer, ser::SerializeTuple}; +use crate::StmResult; use crate::key_registration::RegisteredParty; use crate::{SingleSignature, StmSignatureError}; @@ -28,7 +29,7 @@ impl SingleSignatureWithRegisteredParty { ///Extract a `SingleSignatureWithRegisteredParty` from a byte slice. pub fn from_bytes( bytes: &[u8], - ) -> Result { + ) -> StmResult { let reg_party = RegisteredParty::from_bytes( bytes.get(0..104).ok_or(StmSignatureError::SerializationError)?, )?; diff --git a/mithril-stm/tests/stm_basic.rs b/mithril-stm/tests/stm_basic.rs index 8cc4ff71ac2..2ffa7acf7f7 100644 --- a/mithril-stm/tests/stm_basic.rs +++ b/mithril-stm/tests/stm_basic.rs @@ -1,7 +1,7 @@ use blake2::Blake2b; use digest::consts::U32; use mithril_stm::{ - BasicVerifier, CoreVerifierError, Initializer, Parameters, Signer, SingleSignature, Stake, + AggregationError, BasicVerifier, Initializer, Parameters, Signer, SingleSignature, Stake, VerificationKey, }; use rand_chacha::ChaCha20Rng; @@ -64,10 +64,13 @@ fn test_core_verifier() { "Verification failed: {verify_result:?}" ); } - Err(CoreVerifierError::NoQuorum(nr_indices, _k)) => { - assert!((nr_indices) < params.k); - } - Err(CoreVerifierError::IndexNotUnique) => unreachable!(), - _ => unreachable!(), + Err(error) => match error.downcast_ref::() { + Some(AggregationError::NotEnoughSignatures(nr_indices, _k)) => { + assert!((nr_indices) < ¶ms.k) + } + _ => { + println!("Unexpected error: {:?}", error); + } + }, } } diff --git a/mithril-stm/tests/stm_protocol.rs b/mithril-stm/tests/stm_protocol.rs index 48a8ab44a2e..5df27eea6c2 100644 --- a/mithril-stm/tests/stm_protocol.rs +++ b/mithril-stm/tests/stm_protocol.rs @@ -34,16 +34,21 @@ fn test_full_protocol() { println!("Aggregate ok"); assert!(aggr.verify(&msg, &avk, ¶ms).is_ok()); } - Err(AggregationError::NotEnoughSignatures(n, k)) => { - println!("Not enough signatures"); - assert!(n < params.k && k == params.k) - } - Err(AggregationError::UsizeConversionInvalid) => { - println!("Invalid usize conversion"); - } - Err(AggregationError::UnsupportedProofSystem(_)) => { - println!("Unsupported proof system"); - } + Err(error) => match error.downcast_ref::() { + Some(AggregationError::NotEnoughSignatures(n, k)) => { + println!("Not enough signatures"); + assert!(n < ¶ms.k && k == ¶ms.k) + } + Some(AggregationError::UsizeConversionInvalid) => { + println!("Invalid usize conversion"); + } + Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { + println!("Unsupported proof system: {:?}", aggregate_signature_type); + } + None => { + println!("Unexpected error during aggregation: {:?}", error); + } + }, } } diff --git a/mithril-stm/tests/test_extensions/protocol_phase.rs b/mithril-stm/tests/test_extensions/protocol_phase.rs index 568048ad45d..063ece4fdb8 100644 --- a/mithril-stm/tests/test_extensions/protocol_phase.rs +++ b/mithril-stm/tests/test_extensions/protocol_phase.rs @@ -4,8 +4,8 @@ use rand_core::RngCore; use rayon::prelude::*; use mithril_stm::{ - AggregateSignature, AggregateSignatureType, AggregateVerificationKey, AggregationError, Clerk, - Initializer, KeyRegistration, Parameters, Signer, SingleSignature, Stake, VerificationKey, + AggregateSignature, AggregateSignatureType, AggregateVerificationKey, Clerk, Initializer, + KeyRegistration, Parameters, Signer, SingleSignature, Stake, StmResult, VerificationKey, }; type H = Blake2b; @@ -19,7 +19,7 @@ pub struct InitializationPhaseResult { /// The result of the operation phase of the STM protocol. pub struct OperationPhaseResult { - pub msig: Result, AggregationError>, + pub msig: StmResult>, pub avk: AggregateVerificationKey, pub sigs: Vec, } From f8cf4f3be57e5b2bd33c23f20664b2f26f3258e1 Mon Sep 17 00:00:00 2001 From: curiecrypt Date: Wed, 19 Nov 2025 16:33:01 +0300 Subject: [PATCH 2/3] remove unused error enums --- mithril-stm/README.md | 8 +-- .../src/aggregate_signature/basic_verifier.rs | 8 +-- mithril-stm/src/aggregate_signature/mod.rs | 8 +-- mithril-stm/src/error.rs | 49 ------------------- mithril-stm/src/lib.rs | 4 +- mithril-stm/tests/stm_protocol.rs | 8 +-- 6 files changed, 18 insertions(+), 67 deletions(-) diff --git a/mithril-stm/README.md b/mithril-stm/README.md index cfd232306b5..56cd5ff5726 100644 --- a/mithril-stm/README.md +++ b/mithril-stm/README.md @@ -141,13 +141,13 @@ match msig { println!("Not enough signatures"); assert!(n < ¶ms.k && k == ¶ms.k) }, - Some(AggregationError::UsizeConversionInvalid) => { - println!("Invalid usize conversion"); - }, + // Some(AggregationError::UsizeConversionInvalid) => { + // println!("Invalid usize conversion"); + // }, Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { println!("Unsupported proof system: {:?}", aggregate_signature_type); }, - None => { + _ => { println!("Unexpected error during aggregation: {:?}", error); } }, diff --git a/mithril-stm/src/aggregate_signature/basic_verifier.rs b/mithril-stm/src/aggregate_signature/basic_verifier.rs index 9b4fddda80e..cad572f0176 100644 --- a/mithril-stm/src/aggregate_signature/basic_verifier.rs +++ b/mithril-stm/src/aggregate_signature/basic_verifier.rs @@ -5,8 +5,8 @@ use crate::bls_multi_signature::{BlsSignature, BlsVerificationKey}; use crate::key_registration::RegisteredParty; use crate::merkle_tree::MerkleTreeLeaf; use crate::{ - AggregationError, CoreVerifierError, Index, Parameters, SingleSignature, - SingleSignatureWithRegisteredParty, Stake, StmResult, + AggregationError, Index, Parameters, SingleSignature, SingleSignatureWithRegisteredParty, + Stake, StmResult, }; /// Full node verifier including the list of eligible signers and the total stake of the system. @@ -73,10 +73,10 @@ impl BasicVerifier { } if nr_indices != unique_indices.len() { - return Err(anyhow!(CoreVerifierError::IndexNotUnique)); + return Err(anyhow!(AggregationError::IndexNotUnique)); } if (nr_indices as u64) < parameters.k { - return Err(anyhow!(CoreVerifierError::NoQuorum( + return Err(anyhow!(AggregationError::NotEnoughSignatures( nr_indices as u64, parameters.k ))); diff --git a/mithril-stm/src/aggregate_signature/mod.rs b/mithril-stm/src/aggregate_signature/mod.rs index 4fb16d81be9..b1dcd91b0ea 100644 --- a/mithril-stm/src/aggregate_signature/mod.rs +++ b/mithril-stm/src/aggregate_signature/mod.rs @@ -267,13 +267,13 @@ mod tests { println!("Not enough signatures"); assert!(n < ¶ms.k && k == ¶ms.k) }, - Some(AggregationError::UsizeConversionInvalid) => { - println!("Invalid usize conversion"); - }, + // Some(AggregationError::UsizeConversionInvalid) => { + // println!("Invalid usize conversion"); + // }, Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { println!("Unsupported proof system: {:?}", aggregate_signature_type); }, - None => { + _ => { println!("Unexpected error during aggregation: {:?}", error); } }, diff --git a/mithril-stm/src/error.rs b/mithril-stm/src/error.rs index 6a52dac23c5..da4247312d6 100644 --- a/mithril-stm/src/error.rs +++ b/mithril-stm/src/error.rs @@ -63,22 +63,10 @@ pub enum StmSignatureError { #[error("Received index, {0}, is higher than what the security parameter allows, {1}.")] IndexBoundFailed(u64, u64), - /// MSP.Eval was computed incorrectly - #[error("The claimed evaluation of function phi is incorrect.")] - EvalInvalid([u8; 64]), - /// The lottery was actually lost for the signature #[error("Lottery for this epoch was lost.")] LotteryLost, - /// A party submitted an invalid signature - #[error("A provided signature is invalid")] - SignatureInvalid(BlsSignature), - - /// Batch verification of STM signatures failed - #[error("Batch verification of STM signatures failed")] - BatchInvalid, - /// This error occurs when the the serialization of the raw bytes failed #[error("Invalid bytes")] SerializationError, @@ -91,58 +79,25 @@ pub enum AggregationError { #[error("Not enough signatures. Got only {0} out of {1}.")] NotEnoughSignatures(u64, u64), - /// This error happens when we try to convert a u64 to a usize and it does not fit - #[error("Invalid usize conversion")] - UsizeConversionInvalid, - - /// The proof system used in the aggregate signature is not supported #[error("Unsupported proof system: {0}")] UnsupportedProofSystem(AggregateSignatureType), -} - -/// Errors which can be output by `CoreVerifier`. -#[derive(Debug, Clone, thiserror::Error)] -pub enum CoreVerifierError { - /// No quorum was found - #[error("No Quorum was found. Expected {0} signatures but got {1}")] - NoQuorum(u64, u64), /// There is a duplicate index #[error("Indices are not unique.")] IndexNotUnique, - - /// The aggregated signature is invalid - #[error("Aggregate signature is invalid")] - AggregateSignatureInvalid, - - /// One of the aggregated signatures is invalid - #[error("Individual signature is invalid: {0}")] - IndividualSignatureInvalid(#[source] StmSignatureError), } /// Errors which can be output by Mithril aggregate verification. #[derive(Debug, Clone, thiserror::Error)] pub enum StmAggregateSignatureError { - /// The IVK is invalid after aggregating the keys - #[error("Aggregated key does not correspond to the expected key.")] - IvkInvalid(Box), - /// This error occurs when the the serialization of the raw bytes failed #[error("Invalid bytes")] SerializationError, - /// Invalid merkle batch path - #[error("Batch path does not verify against root")] - PathInvalid(Vec), - /// Batch verification of STM aggregate signatures failed #[error("Batch verification of STM aggregate signatures failed")] BatchInvalid, - /// `CoreVerifier` check failed - #[error("Core verification error: {0}")] - CoreVerificationError(#[source] CoreVerifierError), - /// The proof system used in the aggregate signature is not supported #[error("Unsupported proof system: {0}")] UnsupportedProofSystem(AggregateSignatureType), @@ -155,10 +110,6 @@ pub enum RegisterError { #[error("This key has already been registered.")] KeyRegistered(Box), - /// Verification key is the infinity - #[error("Verification key is the infinity")] - VerificationKeyInfinity(Box), - /// The supplied key is not valid #[error("The verification of correctness of the supplied key is invalid.")] KeyInvalid(Box), diff --git a/mithril-stm/src/lib.rs b/mithril-stm/src/lib.rs index fb5212649d3..3e8186697ea 100644 --- a/mithril-stm/src/lib.rs +++ b/mithril-stm/src/lib.rs @@ -125,8 +125,8 @@ pub use aggregate_signature::{ AggregateSignature, AggregateSignatureType, AggregateVerificationKey, BasicVerifier, Clerk, }; pub use error::{ - AggregationError, CoreVerifierError, MultiSignatureError, RegisterError, - StmAggregateSignatureError, StmSignatureError, + AggregationError, MultiSignatureError, RegisterError, StmAggregateSignatureError, + StmSignatureError, }; pub use key_registration::{ClosedKeyRegistration, KeyRegistration}; pub use parameters::Parameters; diff --git a/mithril-stm/tests/stm_protocol.rs b/mithril-stm/tests/stm_protocol.rs index 5df27eea6c2..4951f9a81cc 100644 --- a/mithril-stm/tests/stm_protocol.rs +++ b/mithril-stm/tests/stm_protocol.rs @@ -39,13 +39,13 @@ fn test_full_protocol() { println!("Not enough signatures"); assert!(n < ¶ms.k && k == ¶ms.k) } - Some(AggregationError::UsizeConversionInvalid) => { - println!("Invalid usize conversion"); - } + // Some(AggregationError::UsizeConversionInvalid) => { + // println!("Invalid usize conversion"); + // } Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { println!("Unsupported proof system: {:?}", aggregate_signature_type); } - None => { + _ => { println!("Unexpected error during aggregation: {:?}", error); } }, From 64256602ef2274aad2a66cead1fd400c5458c229 Mon Sep 17 00:00:00 2001 From: curiecrypt Date: Wed, 19 Nov 2025 16:57:20 +0300 Subject: [PATCH 3/3] change log and crates version --- Cargo.lock | 2 +- mithril-stm/CHANGELOG.md | 6 ++ mithril-stm/Cargo.toml | 2 +- mithril-stm/README.md | 4 +- mithril-stm/src/aggregate_signature/mod.rs | 7 +-- .../proof/concatenation.rs | 16 +++--- .../src/aggregate_signature/signature.rs | 57 ++++++++----------- mithril-stm/src/bls_multi_signature/mod.rs | 5 +- mithril-stm/src/error.rs | 4 +- mithril-stm/src/key_registration.rs | 5 +- mithril-stm/src/lib.rs | 3 +- mithril-stm/src/single_signature/signature.rs | 17 +++--- .../signature_registered_party.rs | 6 +- mithril-stm/tests/stm_basic.rs | 2 +- mithril-stm/tests/stm_protocol.rs | 8 +-- 15 files changed, 65 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34f052251cd..7034440ffee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4146,7 +4146,7 @@ dependencies = [ [[package]] name = "mithril-stm" -version = "0.5.5" +version = "0.6.0" dependencies = [ "anyhow", "blake2 0.10.6", diff --git a/mithril-stm/CHANGELOG.md b/mithril-stm/CHANGELOG.md index 4f2ba827bdb..2df9af05561 100644 --- a/mithril-stm/CHANGELOG.md +++ b/mithril-stm/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.6.0 (11-19-2025) + +### Changed + +- Stm error handling is done with `anyhow`. + ## 0.5.5 (10-13-2025) ### Fixed diff --git a/mithril-stm/Cargo.toml b/mithril-stm/Cargo.toml index af54d8f9c3a..a22098e9ffc 100644 --- a/mithril-stm/Cargo.toml +++ b/mithril-stm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-stm" -version = "0.5.5" +version = "0.6.0" edition = { workspace = true } authors = { workspace = true } homepage = { workspace = true } diff --git a/mithril-stm/README.md b/mithril-stm/README.md index 56cd5ff5726..5a1d5d86523 100644 --- a/mithril-stm/README.md +++ b/mithril-stm/README.md @@ -141,9 +141,7 @@ match msig { println!("Not enough signatures"); assert!(n < ¶ms.k && k == ¶ms.k) }, - // Some(AggregationError::UsizeConversionInvalid) => { - // println!("Invalid usize conversion"); - // }, + Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { println!("Unsupported proof system: {:?}", aggregate_signature_type); }, diff --git a/mithril-stm/src/aggregate_signature/mod.rs b/mithril-stm/src/aggregate_signature/mod.rs index b1dcd91b0ea..65b009189ee 100644 --- a/mithril-stm/src/aggregate_signature/mod.rs +++ b/mithril-stm/src/aggregate_signature/mod.rs @@ -267,14 +267,11 @@ mod tests { println!("Not enough signatures"); assert!(n < ¶ms.k && k == ¶ms.k) }, - // Some(AggregationError::UsizeConversionInvalid) => { - // println!("Invalid usize conversion"); - // }, Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { - println!("Unsupported proof system: {:?}", aggregate_signature_type); + panic!("Unsupported proof system: {:?}", aggregate_signature_type); }, _ => { - println!("Unexpected error during aggregation: {:?}", error); + panic!("Unexpected error during aggregation: {:?}", error); } }, } diff --git a/mithril-stm/src/aggregate_signature/proof/concatenation.rs b/mithril-stm/src/aggregate_signature/proof/concatenation.rs index 0eae91396e6..f619b359efe 100644 --- a/mithril-stm/src/aggregate_signature/proof/concatenation.rs +++ b/mithril-stm/src/aggregate_signature/proof/concatenation.rs @@ -8,8 +8,8 @@ use crate::bls_multi_signature::{BlsSignature, BlsVerificationKey}; use crate::key_registration::RegisteredParty; use crate::merkle_tree::MerkleBatchPath; use crate::{ - AggregateVerificationKey, BasicVerifier, Parameters, SingleSignature, - SingleSignatureWithRegisteredParty, StmAggregateSignatureError, StmResult, + AggregateSignatureError, AggregateVerificationKey, BasicVerifier, Parameters, SingleSignature, + SingleSignatureWithRegisteredParty, StmResult, }; /// `ConcatenationProof` uses the "concatenation" proving system (as described in Section 4.3 of the original paper.) @@ -211,10 +211,10 @@ impl ConcatenationProof { u64_bytes.copy_from_slice( bytes .get(bytes_index..bytes_index + 8) - .ok_or(StmAggregateSignatureError::SerializationError)?, + .ok_or(AggregateSignatureError::SerializationError)?, ); let total_sigs = usize::try_from(u64::from_be_bytes(u64_bytes)) - .map_err(|_| StmAggregateSignatureError::SerializationError)?; + .map_err(|_| AggregateSignatureError::SerializationError)?; bytes_index += 8; let mut sig_reg_list = Vec::with_capacity(total_sigs); @@ -222,14 +222,14 @@ impl ConcatenationProof { u64_bytes.copy_from_slice( bytes .get(bytes_index..bytes_index + 8) - .ok_or(StmAggregateSignatureError::SerializationError)?, + .ok_or(AggregateSignatureError::SerializationError)?, ); let sig_reg_size = usize::try_from(u64::from_be_bytes(u64_bytes)) - .map_err(|_| StmAggregateSignatureError::SerializationError)?; + .map_err(|_| AggregateSignatureError::SerializationError)?; let sig_reg = SingleSignatureWithRegisteredParty::from_bytes::( bytes .get(bytes_index + 8..bytes_index + 8 + sig_reg_size) - .ok_or(StmAggregateSignatureError::SerializationError)?, + .ok_or(AggregateSignatureError::SerializationError)?, )?; bytes_index += 8 + sig_reg_size; sig_reg_list.push(sig_reg); @@ -238,7 +238,7 @@ impl ConcatenationProof { let batch_proof = MerkleBatchPath::from_bytes( bytes .get(bytes_index..) - .ok_or(StmAggregateSignatureError::SerializationError)?, + .ok_or(AggregateSignatureError::SerializationError)?, )?; Ok(ConcatenationProof { diff --git a/mithril-stm/src/aggregate_signature/signature.rs b/mithril-stm/src/aggregate_signature/signature.rs index 182de87957c..dc8c6fb3a77 100644 --- a/mithril-stm/src/aggregate_signature/signature.rs +++ b/mithril-stm/src/aggregate_signature/signature.rs @@ -1,12 +1,12 @@ -use anyhow::anyhow; use std::collections::HashMap; use std::fmt::Display; use std::hash::Hash; +use anyhow::anyhow; use blake2::digest::{Digest, FixedOutput}; use serde::{Deserialize, Serialize}; -use crate::error::StmAggregateSignatureError; +use crate::error::AggregateSignatureError; use crate::merkle_tree::MerkleBatchPath; use crate::{AggregateVerificationKey, Parameters, StmResult}; @@ -103,7 +103,7 @@ impl AggregateSignature { } #[cfg(feature = "future_proof_system")] AggregateSignature::Future => Err(anyhow!( - StmAggregateSignatureError::UnsupportedProofSystem(self.into()) + AggregateSignatureError::UnsupportedProofSystem(self.into()) )), } } @@ -120,36 +120,26 @@ impl AggregateSignature { acc.entry(sig.into()).or_default().push(sig.clone()); acc }); - stm_signatures - .into_iter() - .try_for_each(|(aggregate_signature_type, aggregate_signatures)| { - match aggregate_signature_type { - AggregateSignatureType::Concatenation => { - let aggregate_signatures_length = aggregate_signatures.len(); - let concatenation_proofs = aggregate_signatures - .into_iter() - .filter_map(|s| s.to_concatenation_proof().cloned()) - .collect::>(); - if concatenation_proofs.len() != aggregate_signatures_length { - return Err(anyhow!(StmAggregateSignatureError::BatchInvalid)); - } - - ConcatenationProof::batch_verify( - &concatenation_proofs, - msgs, - avks, - parameters, - ) - } - #[cfg(feature = "future_proof_system")] - AggregateSignatureType::Future => { - Err(anyhow!(StmAggregateSignatureError::UnsupportedProofSystem( - aggregate_signature_type - ))) + stm_signatures.into_iter().try_for_each( + |(aggregate_signature_type, aggregate_signatures)| match aggregate_signature_type { + AggregateSignatureType::Concatenation => { + let aggregate_signatures_length = aggregate_signatures.len(); + let concatenation_proofs = aggregate_signatures + .into_iter() + .filter_map(|s| s.to_concatenation_proof().cloned()) + .collect::>(); + if concatenation_proofs.len() != aggregate_signatures_length { + return Err(anyhow!(AggregateSignatureError::BatchInvalid)); } + + ConcatenationProof::batch_verify(&concatenation_proofs, msgs, avks, parameters) } - }) - .map_err(|_| anyhow!(StmAggregateSignatureError::BatchInvalid)) + #[cfg(feature = "future_proof_system")] + AggregateSignatureType::Future => Err(anyhow!( + AggregateSignatureError::UnsupportedProofSystem(aggregate_signature_type) + )), + }, + ) } /// Convert an aggregate signature to bytes @@ -173,11 +163,10 @@ impl AggregateSignature { /// Extract an aggregate signature from a byte slice. pub fn from_bytes(bytes: &[u8]) -> StmResult { - let proof_type_byte = - bytes.first().ok_or(StmAggregateSignatureError::SerializationError)?; + let proof_type_byte = bytes.first().ok_or(AggregateSignatureError::SerializationError)?; let proof_bytes = &bytes[1..]; let proof_type = AggregateSignatureType::from_byte_encoding_prefix(*proof_type_byte) - .ok_or(StmAggregateSignatureError::SerializationError)?; + .ok_or(AggregateSignatureError::SerializationError)?; match proof_type { AggregateSignatureType::Concatenation => Ok(AggregateSignature::Concatenation( ConcatenationProof::from_bytes(proof_bytes)?, diff --git a/mithril-stm/src/bls_multi_signature/mod.rs b/mithril-stm/src/bls_multi_signature/mod.rs index a1fbf2eee68..9f0ba22cc01 100644 --- a/mithril-stm/src/bls_multi_signature/mod.rs +++ b/mithril-stm/src/bls_multi_signature/mod.rs @@ -94,6 +94,7 @@ mod tests { use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; + use crate::RegisterError; use crate::bls_multi_signature::helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk}; use crate::error::MultiSignatureError; use crate::key_registration::KeyRegistration; @@ -199,8 +200,8 @@ mod tests { assert!( matches!( - error.downcast_ref::(), - Some(MultiSignatureError::VerificationKeyInfinity(_)) + error.downcast_ref::(), + Some(RegisterError::KeyInvalid(_)) ), "Unexpected error: {error:?}"); } diff --git a/mithril-stm/src/error.rs b/mithril-stm/src/error.rs index da4247312d6..800777d2514 100644 --- a/mithril-stm/src/error.rs +++ b/mithril-stm/src/error.rs @@ -58,7 +58,7 @@ pub enum MerkleTreeError { /// Errors which can be output by Mithril single signature verification. #[derive(Debug, Clone, thiserror::Error)] -pub enum StmSignatureError { +pub enum SignatureError { /// There is an index out of bounds #[error("Received index, {0}, is higher than what the security parameter allows, {1}.")] IndexBoundFailed(u64, u64), @@ -89,7 +89,7 @@ pub enum AggregationError { /// Errors which can be output by Mithril aggregate verification. #[derive(Debug, Clone, thiserror::Error)] -pub enum StmAggregateSignatureError { +pub enum AggregateSignatureError { /// This error occurs when the the serialization of the raw bytes failed #[error("Invalid bytes")] SerializationError, diff --git a/mithril-stm/src/key_registration.rs b/mithril-stm/src/key_registration.rs index feb06bd5954..319325ba463 100644 --- a/mithril-stm/src/key_registration.rs +++ b/mithril-stm/src/key_registration.rs @@ -38,7 +38,8 @@ impl KeyRegistration { pk: BlsVerificationKeyProofOfPossession, ) -> StmResult<()> { if let Entry::Vacant(e) = self.keys.entry(pk.vk) { - pk.verify_proof_of_possession()?; + pk.verify_proof_of_possession() + .map_err(|_| RegisterError::KeyInvalid(Box::new(pk)))?; e.insert(stake); return Ok(()); } @@ -141,7 +142,7 @@ mod tests { assert_eq!(fake_it, 0); assert!(a.verify_proof_of_possession().is_err()); }, - _ => {println!("Unexpected error: {error}")} + _ => {panic!("Unexpected error: {error}")} } } } diff --git a/mithril-stm/src/lib.rs b/mithril-stm/src/lib.rs index 3e8186697ea..9030ebd3993 100644 --- a/mithril-stm/src/lib.rs +++ b/mithril-stm/src/lib.rs @@ -125,8 +125,7 @@ pub use aggregate_signature::{ AggregateSignature, AggregateSignatureType, AggregateVerificationKey, BasicVerifier, Clerk, }; pub use error::{ - AggregationError, MultiSignatureError, RegisterError, StmAggregateSignatureError, - StmSignatureError, + AggregateSignatureError, AggregationError, MultiSignatureError, RegisterError, SignatureError, }; pub use key_registration::{ClosedKeyRegistration, KeyRegistration}; pub use parameters::Parameters; diff --git a/mithril-stm/src/single_signature/signature.rs b/mithril-stm/src/single_signature/signature.rs index 1f031cede4a..e55d6cab48d 100644 --- a/mithril-stm/src/single_signature/signature.rs +++ b/mithril-stm/src/single_signature/signature.rs @@ -9,8 +9,7 @@ use serde::{Deserialize, Serialize}; use crate::bls_multi_signature::BlsSignature; use crate::eligibility_check::is_lottery_won; use crate::{ - AggregateVerificationKey, Index, Parameters, Stake, StmResult, StmSignatureError, - VerificationKey, + AggregateVerificationKey, Index, Parameters, SignatureError, Stake, StmResult, VerificationKey, }; use anyhow::{Context, anyhow}; @@ -57,15 +56,13 @@ impl SingleSignature { ) -> StmResult<()> { for &index in &self.indexes { if index > params.m { - return Err(anyhow!(StmSignatureError::IndexBoundFailed( - index, params.m - ))); + return Err(anyhow!(SignatureError::IndexBoundFailed(index, params.m))); } let ev = self.sigma.evaluate_dense_mapping(msg, index); if !is_lottery_won(params.phi_f, ev, *stake, *total_stake) { - return Err(anyhow!(StmSignatureError::LotteryLost)); + return Err(anyhow!(SignatureError::LotteryLost)); } } @@ -99,7 +96,7 @@ impl SingleSignature { pub fn from_bytes(bytes: &[u8]) -> StmResult { let mut u64_bytes = [0u8; 8]; - u64_bytes.copy_from_slice(bytes.get(0..8).ok_or(StmSignatureError::SerializationError)?); + u64_bytes.copy_from_slice(bytes.get(0..8).ok_or(SignatureError::SerializationError)?); let nr_indexes = u64::from_be_bytes(u64_bytes) as usize; let mut indexes = Vec::new(); @@ -107,7 +104,7 @@ impl SingleSignature { u64_bytes.copy_from_slice( bytes .get(8 + i * 8..16 + i * 8) - .ok_or(StmSignatureError::SerializationError)?, + .ok_or(SignatureError::SerializationError)?, ); indexes.push(u64::from_be_bytes(u64_bytes)); } @@ -116,13 +113,13 @@ impl SingleSignature { let sigma = BlsSignature::from_bytes( bytes .get(offset..offset + 48) - .ok_or(StmSignatureError::SerializationError)?, + .ok_or(SignatureError::SerializationError)?, )?; u64_bytes.copy_from_slice( bytes .get(offset + 48..offset + 56) - .ok_or(StmSignatureError::SerializationError)?, + .ok_or(SignatureError::SerializationError)?, ); let signer_index = u64::from_be_bytes(u64_bytes); diff --git a/mithril-stm/src/single_signature/signature_registered_party.rs b/mithril-stm/src/single_signature/signature_registered_party.rs index 23c176e2a13..b3db1bd6e16 100644 --- a/mithril-stm/src/single_signature/signature_registered_party.rs +++ b/mithril-stm/src/single_signature/signature_registered_party.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize, Serializer, ser::SerializeTuple}; use crate::StmResult; use crate::key_registration::RegisteredParty; -use crate::{SingleSignature, StmSignatureError}; +use crate::{SignatureError, SingleSignature}; /// Signature with its registered party. #[derive(Debug, Clone, Hash, Deserialize, Eq, PartialEq, Ord, PartialOrd)] @@ -31,10 +31,10 @@ impl SingleSignatureWithRegisteredParty { bytes: &[u8], ) -> StmResult { let reg_party = RegisteredParty::from_bytes( - bytes.get(0..104).ok_or(StmSignatureError::SerializationError)?, + bytes.get(0..104).ok_or(SignatureError::SerializationError)?, )?; let sig = SingleSignature::from_bytes::( - bytes.get(104..).ok_or(StmSignatureError::SerializationError)?, + bytes.get(104..).ok_or(SignatureError::SerializationError)?, )?; Ok(SingleSignatureWithRegisteredParty { sig, reg_party }) diff --git a/mithril-stm/tests/stm_basic.rs b/mithril-stm/tests/stm_basic.rs index 2ffa7acf7f7..1c37026143f 100644 --- a/mithril-stm/tests/stm_basic.rs +++ b/mithril-stm/tests/stm_basic.rs @@ -69,7 +69,7 @@ fn test_core_verifier() { assert!((nr_indices) < ¶ms.k) } _ => { - println!("Unexpected error: {:?}", error); + panic!("Unexpected error: {:?}", error); } }, } diff --git a/mithril-stm/tests/stm_protocol.rs b/mithril-stm/tests/stm_protocol.rs index 4951f9a81cc..e2cf9c7df07 100644 --- a/mithril-stm/tests/stm_protocol.rs +++ b/mithril-stm/tests/stm_protocol.rs @@ -39,14 +39,12 @@ fn test_full_protocol() { println!("Not enough signatures"); assert!(n < ¶ms.k && k == ¶ms.k) } - // Some(AggregationError::UsizeConversionInvalid) => { - // println!("Invalid usize conversion"); - // } + Some(AggregationError::UnsupportedProofSystem(aggregate_signature_type)) => { - println!("Unsupported proof system: {:?}", aggregate_signature_type); + panic!("Unsupported proof system: {:?}", aggregate_signature_type); } _ => { - println!("Unexpected error during aggregation: {:?}", error); + panic!("Unexpected error during aggregation: {:?}", error); } }, }