diff --git a/Cargo.lock b/Cargo.lock index 1976d4de071..ed7384443a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4147,6 +4147,7 @@ dependencies = [ name = "mithril-stm" version = "0.5.5" dependencies = [ + "anyhow", "blake2 0.10.6", "blst", "criterion", 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..be511e4846b 100644 --- a/mithril-stm/README.md +++ b/mithril-stm/README.md @@ -136,16 +136,15 @@ 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) => assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures { .. }) + | Some(AggregationError::UsizeConversionInvalid) + | Some(AggregationError::UnsupportedProofSystem { .. }) + ), + "Unexpected error: {error}" + ), } ``` diff --git a/mithril-stm/src/aggregate_signature/basic_verifier.rs b/mithril-stm/src/aggregate_signature/basic_verifier.rs index ab59658650f..57e4bb49f6d 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::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,7 +57,7 @@ impl BasicVerifier { signatures: &[SingleSignatureWithRegisteredParty], parameters: &Parameters, msg: &[u8], - ) -> Result<(), CoreVerifierError> { + ) -> StmResult<()> { let mut nr_indices = 0; let mut unique_indices = HashSet::new(); @@ -71,10 +72,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 +97,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 +173,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 +195,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 +224,7 @@ impl BasicVerifier { signatures: &[SingleSignature], parameters: &Parameters, msg: &[u8], - ) -> Result<(), CoreVerifierError> { + ) -> StmResult<()> { let sig_reg_list = signatures .iter() .map(|sig| SingleSignatureWithRegisteredParty { diff --git a/mithril-stm/src/aggregate_signature/clerk.rs b/mithril-stm/src/aggregate_signature/clerk.rs index 62fe9459587..a1f20a38bd7 100644 --- a/mithril-stm/src/aggregate_signature/clerk.rs +++ b/mithril-stm/src/aggregate_signature/clerk.rs @@ -1,10 +1,15 @@ -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 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 +67,7 @@ impl Clerk { &self, sigs: &[SingleSignature], msg: &[u8], - ) -> Result, AggregationError> { + ) -> StmResult> { self.aggregate_signatures_with_type(sigs, msg, AggregateSignatureType::default()) } @@ -72,14 +77,14 @@ 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)?, )), #[cfg(feature = "future_proof_system")] - AggregateSignatureType::Future => Err(AggregationError::UnsupportedProofSystem( - aggregate_signature_type, + AggregateSignatureType::Future => Err(anyhow!( + AggregationError::UnsupportedProofSystem(aggregate_signature_type) )), } } @@ -96,7 +101,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..1ac66ea8923 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], } @@ -262,12 +262,13 @@ mod tests { let verify_result = aggr.verify(&msg, &clerk.compute_aggregate_verification_key(), ¶ms); assert!(verify_result.is_ok(), "Verification failed: {verify_result:?}"); } - Err(AggregationError::NotEnoughSignatures(n, k)) => - assert!(n < params.k || k == params.k), - Err(AggregationError::UsizeConversionInvalid) => - unreachable!(), - Err(AggregationError::UnsupportedProofSystem(_)) => - unreachable!(), + Err(error) => { assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures{..}) + ), + "Unexpected error: {error:?}"); + } } } @@ -303,11 +304,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 +431,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 +564,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..bdb9fcca4f0 100644 --- a/mithril-stm/src/aggregate_signature/proof/concatenation.rs +++ b/mithril-stm/src/aggregate_signature/proof/concatenation.rs @@ -7,8 +7,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 +36,7 @@ impl ConcatenationProof { clerk: &Clerk, sigs: &[SingleSignature], msg: &[u8], - ) -> Result, AggregationError> { + ) -> StmResult> { let sig_reg_list = sigs .iter() .map(|sig| SingleSignatureWithRegisteredParty { @@ -83,7 +83,7 @@ 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(), @@ -117,7 +117,7 @@ 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)?; @@ -131,7 +131,7 @@ impl ConcatenationProof { msgs: &[Vec], avks: &[AggregateVerificationKey], parameters: &[Parameters], - ) -> Result<(), StmAggregateSignatureError> { + ) -> StmResult<()> { let batch_size = stm_signatures.len(); assert_eq!( batch_size, @@ -195,9 +195,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..288d22b7673 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::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> { + ) -> StmResult<()> { let (aggr_vk, aggr_sig) = Self::aggregate(vks, sigs)?; - 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..e1efe91f7c3 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. @@ -98,8 +98,8 @@ impl From for StmSignatureError { } } -impl From> for StmSignatureError { - fn from(e: MerkleTreeError) -> Self { +impl From for StmSignatureError { + fn from(e: MerkleTreeError) -> Self { match e { MerkleTreeError::SerializationError => Self::SerializationError, _ => unreachable!(), @@ -175,7 +175,7 @@ impl From for CoreVerifierError { /// 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 +186,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,8 +201,8 @@ pub enum StmAggregateSignatureError { UnsupportedProofSystem(AggregateSignatureType), } -impl From> for StmAggregateSignatureError { - fn from(e: MerkleTreeError) -> Self { +impl From for StmAggregateSignatureError { + fn from(e: MerkleTreeError) -> Self { match e { MerkleTreeError::BatchPathInvalid(e) => Self::PathInvalid(e), MerkleTreeError::SerializationError => Self::SerializationError, @@ -211,7 +211,7 @@ impl From> for StmAggregateSignature } } -impl From for StmAggregateSignatureError { +impl From for StmAggregateSignatureError { fn from(e: MultiSignatureError) -> Self { match e { MultiSignatureError::AggregateSignatureInvalid => { @@ -233,13 +233,13 @@ impl From for StmAggregateSignatur } } -impl From for StmAggregateSignatureError { +impl From for StmAggregateSignatureError { fn from(e: CoreVerifierError) -> Self { Self::CoreVerificationError(e) } } -impl From for StmAggregateSignatureError { +impl From for StmAggregateSignatureError { fn from(e: StmSignatureError) -> Self { match e { StmSignatureError::SerializationError => Self::SerializationError, @@ -285,6 +285,7 @@ impl From for RegisterError { /// If verifying a single signature, the signature should be provided. If verifying a multi-sig, /// no need to provide the signature +#[allow(dead_code)] pub(crate) fn blst_err_to_mithril( e: BLST_ERROR, sig: Option, @@ -311,3 +312,32 @@ pub(crate) fn blst_err_to_mithril( _ => Err(MultiSignatureError::SerializationError), } } + +pub(crate) fn blst_error_to_stm_error( + e: BLST_ERROR, + sig: Option, + key: Option, +) -> StmResult<()> { + match e { + BLST_ERROR::BLST_SUCCESS => Ok(()), + BLST_ERROR::BLST_PK_IS_INFINITY => { + if let Some(s) = sig { + return Err(anyhow!(MultiSignatureError::SignatureInfinity(s))); + } + if let Some(vk) = key { + return Err(anyhow!(MultiSignatureError::VerificationKeyInfinity( + Box::new(vk) + ))); + } + Err(anyhow!(MultiSignatureError::SerializationError)) + } + BLST_ERROR::BLST_VERIFY_FAIL => { + if let Some(s) = sig { + Err(anyhow!(MultiSignatureError::SignatureInvalid(s))) + } else { + Err(anyhow!(MultiSignatureError::AggregateSignatureInvalid)) + } + } + _ => Err(anyhow!(MultiSignatureError::SerializationError)), + } +} diff --git a/mithril-stm/src/key_registration.rs b/mithril-stm/src/key_registration.rs index 839ea005267..1a6c680d9ae 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. @@ -92,7 +93,7 @@ mod tests { use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; - use crate::bls_multi_signature::BlsSigningKey; + use crate::{bls_multi_signature::BlsSigningKey, error::MultiSignatureError}; use super::*; @@ -126,23 +127,23 @@ 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) => { assert!( + matches!( + error.downcast_ref::(), + Some(RegisterError::KeyRegistered{..}) + ) | matches!( + error.downcast_ref::(), + Some(MultiSignatureError::KeyInvalid{..}) + ), + "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..cb23a152f95 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(()) //! # } @@ -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..d768d5b4070 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::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; @@ -249,7 +246,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 +260,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 +279,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..43bf8140190 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::anyhow; /// Signature created by a single party who has won the lottery. #[derive(Debug, Clone, Serialize, Deserialize)] @@ -33,7 +35,7 @@ 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())?; Ok(()) @@ -46,16 +48,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 +90,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,7 +147,7 @@ impl SingleSignature { stake: &Stake, msg: &[u8], total_stake: &Stake, - ) -> Result<(), StmSignatureError> { + ) -> StmResult<()> { self.sigma.verify(msg, pk)?; self.check_indices(params, stake, msg, total_stake)?; @@ -161,7 +163,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..6ef382ca72d 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,12 @@ 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) => assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures { .. }) + ), + "Unexpected error: {error}" + ), } } diff --git a/mithril-stm/tests/stm_protocol.rs b/mithril-stm/tests/stm_protocol.rs index 48a8ab44a2e..f78b761fa9c 100644 --- a/mithril-stm/tests/stm_protocol.rs +++ b/mithril-stm/tests/stm_protocol.rs @@ -34,16 +34,15 @@ 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) => assert!( + matches!( + error.downcast_ref::(), + Some(AggregationError::NotEnoughSignatures { .. }) + | Some(AggregationError::UsizeConversionInvalid) + | Some(AggregationError::UnsupportedProofSystem { .. }) + ), + "Unexpected error: {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, }