diff --git a/zk-token-sdk/src/encryption/discrete_log.rs b/zk-token-sdk/src/encryption/discrete_log.rs index 7d45d114a..229517455 100644 --- a/zk-token-sdk/src/encryption/discrete_log.rs +++ b/zk-token-sdk/src/encryption/discrete_log.rs @@ -17,7 +17,7 @@ #![cfg(not(target_os = "solana"))] use { - crate::encryption::errors::EncryptionError, + crate::encryption::errors::DiscreteLogError, curve25519_dalek::{ constants::RISTRETTO_BASEPOINT_POINT as G, ristretto::RistrettoPoint, @@ -100,10 +100,10 @@ impl DiscreteLog { } /// Adjusts number of threads in a discrete log instance. - pub fn num_threads(&mut self, num_threads: usize) -> Result<(), EncryptionError> { + pub fn num_threads(&mut self, num_threads: usize) -> Result<(), DiscreteLogError> { // number of threads must be a positive power-of-two integer if num_threads == 0 || (num_threads & (num_threads - 1)) != 0 || num_threads > 65536 { - return Err(EncryptionError::DiscreteLogThreads); + return Err(DiscreteLogError::DiscreteLogThreads); } self.num_threads = num_threads; @@ -117,9 +117,9 @@ impl DiscreteLog { pub fn set_compression_batch_size( &mut self, compression_batch_size: usize, - ) -> Result<(), EncryptionError> { + ) -> Result<(), DiscreteLogError> { if compression_batch_size >= TWO16 as usize { - return Err(EncryptionError::DiscreteLogBatchSize); + return Err(DiscreteLogError::DiscreteLogBatchSize); } self.compression_batch_size = compression_batch_size; diff --git a/zk-token-sdk/src/encryption/errors.rs b/zk-token-sdk/src/encryption/errors.rs index e076da08c..d644787f5 100644 --- a/zk-token-sdk/src/encryption/errors.rs +++ b/zk-token-sdk/src/encryption/errors.rs @@ -2,7 +2,7 @@ use thiserror::Error; #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum EncryptionError { +pub enum DiscreteLogError { #[error("discrete log number of threads not power-of-two")] DiscreteLogThreads, #[error("discrete log batch size too large")] diff --git a/zk-token-sdk/src/errors.rs b/zk-token-sdk/src/errors.rs index 55e29fbec..e9e36e43f 100644 --- a/zk-token-sdk/src/errors.rs +++ b/zk-token-sdk/src/errors.rs @@ -10,30 +10,46 @@ pub enum ProofError { TransferAmount, #[error("proof generation failed")] Generation, - #[error("proof failed to verify")] - RangeProof, - #[error("equality proof failed to verify")] - EqualityProof, - #[error("fee proof failed to verify")] - FeeProof, - #[error("zero-balance proof failed to verify")] - ZeroBalanceProof, - #[error("validity proof failed to verify")] - ValidityProof, - #[error("public-key sigma proof failed to verify")] - PubkeySigmaProof, + #[error("proof verification failed")] + VerificationError(ProofType, ProofVerificationError), #[error("failed to decrypt ciphertext")] Decryption, #[error("invalid ciphertext data")] CiphertextDeserialization, - #[error("invalid scalar data")] - ScalarDeserialization, - #[error("invalid public key data")] + #[error("invalid pubkey data")] PubkeyDeserialization, - #[error("ciphertext does not exist in proof data")] + #[error("ciphertext does not exist in instruction data")] MissingCiphertext, - #[error("transfer amount split failed")] - TransferSplit, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ProofType { + EqualityProof, + ValidityProof, + ZeroBalanceProof, + FeeSigmaProof, + PubkeyValidityProof, + RangeProof, +} + +#[derive(Error, Clone, Debug, Eq, PartialEq)] +pub enum ProofVerificationError { + #[error("required algebraic relation does not hold")] + AlgebraicRelation, + #[error("malformed proof")] + Deserialization, + #[error("multiscalar multiplication failed")] + MultiscalarMul, + #[error("transcript failed to produce a challenge")] + Transcript(#[from] TranscriptError), + #[error( + "attempted to verify range proof with a non-power-of-two bit size or bit size is too big" + )] + InvalidBitSize, + #[error("insufficient generators for the proof")] + InvalidGeneratorsLength, + #[error("number of blinding factors do not match the number of values")] + WrongNumBlindingFactors, } #[derive(Error, Clone, Debug, Eq, PartialEq)] @@ -43,36 +59,36 @@ pub enum TranscriptError { } impl From for ProofError { - fn from(_err: RangeProofError) -> Self { - Self::RangeProof + fn from(err: RangeProofError) -> Self { + Self::VerificationError(ProofType::RangeProof, err.0) } } impl From for ProofError { - fn from(_err: EqualityProofError) -> Self { - Self::EqualityProof + fn from(err: EqualityProofError) -> Self { + Self::VerificationError(ProofType::EqualityProof, err.0) } } impl From for ProofError { - fn from(_err: FeeSigmaProofError) -> Self { - Self::FeeProof + fn from(err: FeeSigmaProofError) -> Self { + Self::VerificationError(ProofType::FeeSigmaProof, err.0) } } impl From for ProofError { - fn from(_err: ZeroBalanceProofError) -> Self { - Self::ZeroBalanceProof + fn from(err: ZeroBalanceProofError) -> Self { + Self::VerificationError(ProofType::ZeroBalanceProof, err.0) } } impl From for ProofError { - fn from(_err: ValidityProofError) -> Self { - Self::ValidityProof + fn from(err: ValidityProofError) -> Self { + Self::VerificationError(ProofType::ValidityProof, err.0) } } -impl From for ProofError { - fn from(_err: PubkeySigmaProofError) -> Self { - Self::PubkeySigmaProof +impl From for ProofError { + fn from(err: PubkeyValidityProofError) -> Self { + Self::VerificationError(ProofType::PubkeyValidityProof, err.0) } } diff --git a/zk-token-sdk/src/instruction/transfer.rs b/zk-token-sdk/src/instruction/transfer.rs index 742ab6442..362ed4655 100644 --- a/zk-token-sdk/src/instruction/transfer.rs +++ b/zk-token-sdk/src/instruction/transfer.rs @@ -455,11 +455,11 @@ impl TransferPubkeys { let (source_pubkey, destination_pubkey, auditor_pubkey) = array_refs![bytes, 32, 32, 32]; let source_pubkey = - ElGamalPubkey::from_bytes(source_pubkey).ok_or(ProofError::Decryption)?; - let destination_pubkey = - ElGamalPubkey::from_bytes(destination_pubkey).ok_or(ProofError::Decryption)?; + ElGamalPubkey::from_bytes(source_pubkey).ok_or(ProofError::PubkeyDeserialization)?; + let destination_pubkey = ElGamalPubkey::from_bytes(destination_pubkey) + .ok_or(ProofError::PubkeyDeserialization)?; let auditor_pubkey = - ElGamalPubkey::from_bytes(auditor_pubkey).ok_or(ProofError::Decryption)?; + ElGamalPubkey::from_bytes(auditor_pubkey).ok_or(ProofError::PubkeyDeserialization)?; Ok(Self { source_pubkey, diff --git a/zk-token-sdk/src/macros.rs b/zk-token-sdk/src/macros.rs index 6351ba942..cf7a3836e 100644 --- a/zk-token-sdk/src/macros.rs +++ b/zk-token-sdk/src/macros.rs @@ -74,3 +74,13 @@ macro_rules! define_mul_variants { } }; } + +macro_rules! impl_from_transcript_error { + ($sigma_error_type:ty) => { + impl From for $sigma_error_type { + fn from(err: TranscriptError) -> Self { + ProofVerificationError::Transcript(err).into() + } + } + }; +} diff --git a/zk-token-sdk/src/range_proof/errors.rs b/zk-token-sdk/src/range_proof/errors.rs index b8766a231..f832365ff 100644 --- a/zk-token-sdk/src/range_proof/errors.rs +++ b/zk-token-sdk/src/range_proof/errors.rs @@ -1,26 +1,10 @@ //! Errors related to proving and verifying range proofs. -use {crate::errors::TranscriptError, thiserror::Error}; +use { + crate::errors::{ProofVerificationError, TranscriptError}, + thiserror::Error, +}; #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum RangeProofError { - #[error("the required algebraic relation does not hold")] - AlgebraicRelation, - #[error("malformed proof")] - Format, - #[error("attempted to create a proof with a non-power-of-two bitsize or bitsize too big")] - InvalidBitsize, - #[error("insufficient generators for the proof")] - InvalidGeneratorsLength, - #[error("multiscalar multiplication failed")] - MultiscalarMul, - #[error("transcript failed to produce a challenge")] - Transcript, - #[error("number of blinding factors do not match the number of values")] - WrongNumBlindingFactors, -} - -impl From for RangeProofError { - fn from(_err: TranscriptError) -> Self { - Self::Transcript - } -} +#[error("range proof verification failed: {0}")] +pub struct RangeProofError(#[from] pub(crate) ProofVerificationError); +impl_from_transcript_error!(RangeProofError); diff --git a/zk-token-sdk/src/range_proof/inner_product.rs b/zk-token-sdk/src/range_proof/inner_product.rs index 7cd500b0e..db96928eb 100644 --- a/zk-token-sdk/src/range_proof/inner_product.rs +++ b/zk-token-sdk/src/range_proof/inner_product.rs @@ -1,5 +1,6 @@ use { crate::{ + errors::ProofVerificationError, range_proof::{errors::RangeProofError, util}, transcript::TranscriptProtocol, }, @@ -208,10 +209,10 @@ impl InnerProductProof { if lg_n >= 32 { // 4 billion multiplications should be enough for anyone // and this check prevents overflow in 1<, _>>()?; let Rs = self .R_vec .iter() - .map(|p| p.decompress().ok_or(RangeProofError::Format)) + .map(|p| { + p.decompress() + .ok_or(ProofVerificationError::Deserialization) + }) .collect::, _>>()?; let expect_P = RistrettoPoint::vartime_multiscalar_mul( @@ -323,7 +330,7 @@ impl InnerProductProof { if expect_P == *P { Ok(()) } else { - Err(RangeProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -360,18 +367,18 @@ impl InnerProductProof { pub fn from_bytes(slice: &[u8]) -> Result { let b = slice.len(); if b % 32 != 0 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let num_elements = b / 32; if num_elements < 2 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } if (num_elements - 2) % 2 != 0 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let lg_n = (num_elements - 2) / 2; if lg_n >= 32 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let mut L_vec: Vec = Vec::with_capacity(lg_n); @@ -384,9 +391,9 @@ impl InnerProductProof { let pos = 2 * lg_n * 32; let a = Scalar::from_canonical_bytes(util::read32(&slice[pos..])) - .ok_or(RangeProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let b = Scalar::from_canonical_bytes(util::read32(&slice[pos + 32..])) - .ok_or(RangeProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; Ok(InnerProductProof { L_vec, R_vec, a, b }) } diff --git a/zk-token-sdk/src/range_proof/mod.rs b/zk-token-sdk/src/range_proof/mod.rs index 2a19e8728..f357bc88f 100644 --- a/zk-token-sdk/src/range_proof/mod.rs +++ b/zk-token-sdk/src/range_proof/mod.rs @@ -8,6 +8,7 @@ use { use { crate::{ encryption::pedersen::{G, H}, + errors::ProofVerificationError, range_proof::{ errors::RangeProofError, generators::BulletproofGens, inner_product::InnerProductProof, }, @@ -232,7 +233,7 @@ impl RangeProof { let bp_gens = BulletproofGens::new(nm); if !nm.is_power_of_two() { - return Err(RangeProofError::InvalidBitsize); + return Err(ProofVerificationError::InvalidBitSize.into()); } // append proof data to transcript and derive appropriate challenge scalars @@ -310,12 +311,12 @@ impl RangeProof { .chain(bp_gens.H(nm).map(|&x| Some(x))) .chain(comms.iter().map(|V| Some(*V.get_point()))), ) - .ok_or(RangeProofError::MultiscalarMul)?; + .ok_or(ProofVerificationError::MultiscalarMul)?; if mega_check.is_identity() { Ok(()) } else { - Err(RangeProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -338,10 +339,10 @@ impl RangeProof { // changed. pub fn from_bytes(slice: &[u8]) -> Result { if slice.len() % 32 != 0 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } if slice.len() < 7 * 32 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let A = CompressedRistretto(util::read32(&slice[0..])); @@ -350,11 +351,11 @@ impl RangeProof { let T_2 = CompressedRistretto(util::read32(&slice[3 * 32..])); let t_x = Scalar::from_canonical_bytes(util::read32(&slice[4 * 32..])) - .ok_or(RangeProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let t_x_blinding = Scalar::from_canonical_bytes(util::read32(&slice[5 * 32..])) - .ok_or(RangeProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let e_blinding = Scalar::from_canonical_bytes(util::read32(&slice[6 * 32..])) - .ok_or(RangeProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let ipp_proof = InnerProductProof::from_bytes(&slice[7 * 32..])?; diff --git a/zk-token-sdk/src/sigma_proofs/equality_proof.rs b/zk-token-sdk/src/sigma_proofs/equality_proof.rs index 79df896ce..02df193e3 100644 --- a/zk-token-sdk/src/sigma_proofs/equality_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/equality_proof.rs @@ -12,9 +12,12 @@ #[cfg(not(target_os = "solana"))] use { - crate::encryption::{ - elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey}, - pedersen::{PedersenCommitment, PedersenOpening, G, H}, + crate::{ + encryption::{ + elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey}, + pedersen::{PedersenCommitment, PedersenOpening, G, H}, + }, + errors::ProofVerificationError, }, curve25519_dalek::traits::MultiscalarMul, rand::rngs::OsRng, @@ -153,9 +156,18 @@ impl CtxtCommEqualityProof { let ww_negated = -&ww; // check that the required algebraic condition holds - let Y_0 = self.Y_0.decompress().ok_or(EqualityProofError::Format)?; - let Y_1 = self.Y_1.decompress().ok_or(EqualityProofError::Format)?; - let Y_2 = self.Y_2.decompress().ok_or(EqualityProofError::Format)?; + let Y_0 = self + .Y_0 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_1 = self + .Y_1 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_2 = self + .Y_2 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; let check = RistrettoPoint::vartime_multiscalar_mul( vec![ @@ -189,7 +201,7 @@ impl CtxtCommEqualityProof { if check.is_identity() { Ok(()) } else { - Err(EqualityProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -206,7 +218,7 @@ impl CtxtCommEqualityProof { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 192 { - return Err(EqualityProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let bytes = array_ref![bytes, 0, 192]; @@ -216,9 +228,12 @@ impl CtxtCommEqualityProof { let Y_1 = CompressedRistretto::from_slice(Y_1); let Y_2 = CompressedRistretto::from_slice(Y_2); - let z_s = Scalar::from_canonical_bytes(*z_s).ok_or(EqualityProofError::Format)?; - let z_x = Scalar::from_canonical_bytes(*z_x).ok_or(EqualityProofError::Format)?; - let z_r = Scalar::from_canonical_bytes(*z_r).ok_or(EqualityProofError::Format)?; + let z_s = + Scalar::from_canonical_bytes(*z_s).ok_or(ProofVerificationError::Deserialization)?; + let z_x = + Scalar::from_canonical_bytes(*z_x).ok_or(ProofVerificationError::Deserialization)?; + let z_r = + Scalar::from_canonical_bytes(*z_r).ok_or(ProofVerificationError::Deserialization)?; Ok(CtxtCommEqualityProof { Y_0, @@ -368,10 +383,22 @@ impl CtxtCtxtEqualityProof { let www_negated = -&www; // check that the required algebraic condition holds - let Y_0 = self.Y_0.decompress().ok_or(EqualityProofError::Format)?; - let Y_1 = self.Y_1.decompress().ok_or(EqualityProofError::Format)?; - let Y_2 = self.Y_2.decompress().ok_or(EqualityProofError::Format)?; - let Y_3 = self.Y_3.decompress().ok_or(EqualityProofError::Format)?; + let Y_0 = self + .Y_0 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_1 = self + .Y_1 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_2 = self + .Y_2 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_3 = self + .Y_3 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; let check = RistrettoPoint::vartime_multiscalar_mul( vec![ @@ -411,7 +438,7 @@ impl CtxtCtxtEqualityProof { if check.is_identity() { Ok(()) } else { - Err(EqualityProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -429,7 +456,7 @@ impl CtxtCtxtEqualityProof { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 224 { - return Err(EqualityProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let bytes = array_ref![bytes, 0, 224]; @@ -440,9 +467,12 @@ impl CtxtCtxtEqualityProof { let Y_2 = CompressedRistretto::from_slice(Y_2); let Y_3 = CompressedRistretto::from_slice(Y_3); - let z_s = Scalar::from_canonical_bytes(*z_s).ok_or(EqualityProofError::Format)?; - let z_x = Scalar::from_canonical_bytes(*z_x).ok_or(EqualityProofError::Format)?; - let z_r = Scalar::from_canonical_bytes(*z_r).ok_or(EqualityProofError::Format)?; + let z_s = + Scalar::from_canonical_bytes(*z_s).ok_or(ProofVerificationError::Deserialization)?; + let z_x = + Scalar::from_canonical_bytes(*z_x).ok_or(ProofVerificationError::Deserialization)?; + let z_r = + Scalar::from_canonical_bytes(*z_r).ok_or(ProofVerificationError::Deserialization)?; Ok(CtxtCtxtEqualityProof { Y_0, diff --git a/zk-token-sdk/src/sigma_proofs/errors.rs b/zk-token-sdk/src/sigma_proofs/errors.rs index b42d8c96b..117d5c44d 100644 --- a/zk-token-sdk/src/sigma_proofs/errors.rs +++ b/zk-token-sdk/src/sigma_proofs/errors.rs @@ -1,92 +1,30 @@ //! Errors related to proving and verifying sigma proofs. -use {crate::errors::TranscriptError, thiserror::Error}; +use { + crate::errors::{ProofVerificationError, TranscriptError}, + thiserror::Error, +}; #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum EqualityProofError { - #[error("the required algebraic relation does not hold")] - AlgebraicRelation, - #[error("malformed proof")] - Format, - #[error("multiscalar multiplication failed")] - MultiscalarMul, - #[error("transcript failed to produce a challenge")] - Transcript, -} - -impl From for EqualityProofError { - fn from(_err: TranscriptError) -> Self { - Self::Transcript - } -} +#[error("equality proof verification failed: {0}")] +pub struct EqualityProofError(#[from] pub(crate) ProofVerificationError); +impl_from_transcript_error!(EqualityProofError); #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum ValidityProofError { - #[error("the required algebraic relation does not hold")] - AlgebraicRelation, - #[error("malformed proof")] - Format, - #[error("multiscalar multiplication failed")] - MultiscalarMul, - #[error("transcript failed to produce a challenge")] - Transcript, -} - -impl From for ValidityProofError { - fn from(_err: TranscriptError) -> Self { - Self::Transcript - } -} +#[error("validity proof verification failed: {0}")] +pub struct ValidityProofError(#[from] pub(crate) ProofVerificationError); +impl_from_transcript_error!(ValidityProofError); #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum ZeroBalanceProofError { - #[error("the required algebraic relation does not hold")] - AlgebraicRelation, - #[error("malformed proof")] - Format, - #[error("multiscalar multiplication failed")] - MultiscalarMul, - #[error("transcript failed to produce a challenge")] - Transcript, -} - -impl From for ZeroBalanceProofError { - fn from(_err: TranscriptError) -> Self { - Self::Transcript - } -} +#[error("zero-balance proof verification failed: {0}")] +pub struct ZeroBalanceProofError(#[from] pub(crate) ProofVerificationError); +impl_from_transcript_error!(ZeroBalanceProofError); #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum FeeSigmaProofError { - #[error("the required algebraic relation does not hold")] - AlgebraicRelation, - #[error("malformed proof")] - Format, - #[error("multiscalar multiplication failed")] - MultiscalarMul, - #[error("transcript failed to produce a challenge")] - Transcript, -} - -impl From for FeeSigmaProofError { - fn from(_err: TranscriptError) -> Self { - Self::Transcript - } -} +#[error("fee sigma proof verification failed: {0}")] +pub struct FeeSigmaProofError(#[from] pub(crate) ProofVerificationError); +impl_from_transcript_error!(FeeSigmaProofError); #[derive(Error, Clone, Debug, Eq, PartialEq)] -pub enum PubkeySigmaProofError { - #[error("the required algebraic relation does not hold")] - AlgebraicRelation, - #[error("malformed proof")] - Format, - #[error("multiscalar multiplication failed")] - MultiscalarMul, - #[error("transcript failed to produce a challenge")] - Transcript, -} - -impl From for PubkeySigmaProofError { - fn from(_err: TranscriptError) -> Self { - Self::Transcript - } -} +#[error("public key validity proof verification failed: {0}")] +pub struct PubkeyValidityProofError(#[from] pub(crate) ProofVerificationError); +impl_from_transcript_error!(PubkeyValidityProofError); diff --git a/zk-token-sdk/src/sigma_proofs/fee_proof.rs b/zk-token-sdk/src/sigma_proofs/fee_proof.rs index ff70586bf..6602a6c15 100644 --- a/zk-token-sdk/src/sigma_proofs/fee_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/fee_proof.rs @@ -8,7 +8,10 @@ use { rand::rngs::OsRng, }; use { - crate::{sigma_proofs::errors::FeeSigmaProofError, transcript::TranscriptProtocol}, + crate::{ + errors::ProofVerificationError, sigma_proofs::errors::FeeSigmaProofError, + transcript::TranscriptProtocol, + }, arrayref::{array_ref, array_refs}, curve25519_dalek::{ ristretto::{CompressedRistretto, RistrettoPoint}, @@ -284,19 +287,19 @@ impl FeeSigmaProof { .fee_max_proof .Y_max_proof .decompress() - .ok_or(FeeSigmaProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let z_max = self.fee_max_proof.z_max_proof; let Y_delta_real = self .fee_equality_proof .Y_delta .decompress() - .ok_or(FeeSigmaProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let Y_claimed = self .fee_equality_proof .Y_claimed .decompress() - .ok_or(FeeSigmaProofError::Format)?; + .ok_or(ProofVerificationError::Deserialization)?; let z_x = self.fee_equality_proof.z_x; let z_delta_real = self.fee_equality_proof.z_delta; let z_claimed = self.fee_equality_proof.z_claimed; @@ -342,7 +345,7 @@ impl FeeSigmaProof { if check.is_identity() { Ok(()) } else { - Err(FeeSigmaProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -361,7 +364,7 @@ impl FeeSigmaProof { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 256 { - return Err(FeeSigmaProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let bytes = array_ref![bytes, 0, 256]; @@ -369,17 +372,19 @@ impl FeeSigmaProof { array_refs![bytes, 32, 32, 32, 32, 32, 32, 32, 32]; let Y_max_proof = CompressedRistretto::from_slice(Y_max_proof); - let z_max_proof = - Scalar::from_canonical_bytes(*z_max_proof).ok_or(FeeSigmaProofError::Format)?; - let c_max_proof = - Scalar::from_canonical_bytes(*c_max_proof).ok_or(FeeSigmaProofError::Format)?; + let z_max_proof = Scalar::from_canonical_bytes(*z_max_proof) + .ok_or(ProofVerificationError::Deserialization)?; + let c_max_proof = Scalar::from_canonical_bytes(*c_max_proof) + .ok_or(ProofVerificationError::Deserialization)?; let Y_delta = CompressedRistretto::from_slice(Y_delta); let Y_claimed = CompressedRistretto::from_slice(Y_claimed); - let z_x = Scalar::from_canonical_bytes(*z_x).ok_or(FeeSigmaProofError::Format)?; - let z_delta = Scalar::from_canonical_bytes(*z_delta).ok_or(FeeSigmaProofError::Format)?; - let z_claimed = - Scalar::from_canonical_bytes(*z_claimed).ok_or(FeeSigmaProofError::Format)?; + let z_x = + Scalar::from_canonical_bytes(*z_x).ok_or(ProofVerificationError::Deserialization)?; + let z_delta = Scalar::from_canonical_bytes(*z_delta) + .ok_or(ProofVerificationError::Deserialization)?; + let z_claimed = Scalar::from_canonical_bytes(*z_claimed) + .ok_or(ProofVerificationError::Deserialization)?; Ok(Self { fee_max_proof: FeeMaxProof { diff --git a/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs b/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs index 79378ff80..bd611fc81 100644 --- a/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs @@ -17,7 +17,10 @@ use { zeroize::Zeroize, }; use { - crate::{sigma_proofs::errors::PubkeySigmaProofError, transcript::TranscriptProtocol}, + crate::{ + errors::ProofVerificationError, sigma_proofs::errors::PubkeyValidityProofError, + transcript::TranscriptProtocol, + }, arrayref::{array_ref, array_refs}, curve25519_dalek::{ ristretto::{CompressedRistretto, RistrettoPoint}, @@ -87,7 +90,7 @@ impl PubkeySigmaProof { self, elgamal_pubkey: &ElGamalPubkey, transcript: &mut Transcript, - ) -> Result<(), PubkeySigmaProofError> { + ) -> Result<(), PubkeyValidityProofError> { transcript.pubkey_proof_domain_sep(); // extract the relvant scalar and Ristretto points from the input @@ -98,7 +101,10 @@ impl PubkeySigmaProof { let c = transcript.challenge_scalar(b"c"); // check that the required algebraic condition holds - let Y = self.Y.decompress().ok_or(PubkeySigmaProofError::Format)?; + let Y = self + .Y + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; let check = RistrettoPoint::vartime_multiscalar_mul( vec![&self.z, &(-&c), &(-&Scalar::one())], @@ -108,7 +114,7 @@ impl PubkeySigmaProof { if check.is_identity() { Ok(()) } else { - Err(PubkeySigmaProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -119,16 +125,16 @@ impl PubkeySigmaProof { buf } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 64 { - return Err(PubkeySigmaProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let bytes = array_ref![bytes, 0, 64]; let (Y, z) = array_refs![bytes, 32, 32]; let Y = CompressedRistretto::from_slice(Y); - let z = Scalar::from_canonical_bytes(*z).ok_or(PubkeySigmaProofError::Format)?; + let z = Scalar::from_canonical_bytes(*z).ok_or(ProofVerificationError::Deserialization)?; Ok(PubkeySigmaProof { Y, z }) } diff --git a/zk-token-sdk/src/sigma_proofs/validity_proof.rs b/zk-token-sdk/src/sigma_proofs/validity_proof.rs index de45beaf0..ee55d0c02 100644 --- a/zk-token-sdk/src/sigma_proofs/validity_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/validity_proof.rs @@ -10,9 +10,12 @@ #[cfg(not(target_os = "solana"))] use { - crate::encryption::{ - elgamal::{DecryptHandle, ElGamalPubkey}, - pedersen::{PedersenCommitment, PedersenOpening, G, H}, + crate::{ + encryption::{ + elgamal::{DecryptHandle, ElGamalPubkey}, + pedersen::{PedersenCommitment, PedersenOpening, G, H}, + }, + errors::ProofVerificationError, }, curve25519_dalek::traits::MultiscalarMul, rand::rngs::OsRng, @@ -137,9 +140,18 @@ impl ValidityProof { let ww_negated = -&ww; // check the required algebraic conditions - let Y_0 = self.Y_0.decompress().ok_or(ValidityProofError::Format)?; - let Y_1 = self.Y_1.decompress().ok_or(ValidityProofError::Format)?; - let Y_2 = self.Y_2.decompress().ok_or(ValidityProofError::Format)?; + let Y_0 = self + .Y_0 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_1 = self + .Y_1 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_2 = self + .Y_2 + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; let P_dest = destination_pubkey.get_point(); let P_auditor = auditor_pubkey.get_point(); @@ -178,7 +190,7 @@ impl ValidityProof { if check.is_identity() { Ok(()) } else { - Err(ValidityProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -194,7 +206,7 @@ impl ValidityProof { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 160 { - return Err(ValidityProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let bytes = array_ref![bytes, 0, 160]; @@ -204,8 +216,10 @@ impl ValidityProof { let Y_1 = CompressedRistretto::from_slice(Y_1); let Y_2 = CompressedRistretto::from_slice(Y_2); - let z_r = Scalar::from_canonical_bytes(*z_r).ok_or(ValidityProofError::Format)?; - let z_x = Scalar::from_canonical_bytes(*z_x).ok_or(ValidityProofError::Format)?; + let z_r = + Scalar::from_canonical_bytes(*z_r).ok_or(ProofVerificationError::Deserialization)?; + let z_x = + Scalar::from_canonical_bytes(*z_x).ok_or(ProofVerificationError::Deserialization)?; Ok(ValidityProof { Y_0, diff --git a/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs b/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs index cf77cd0a8..14afd2830 100644 --- a/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs @@ -9,9 +9,12 @@ #[cfg(not(target_os = "solana"))] use { - crate::encryption::{ - elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey}, - pedersen::H, + crate::{ + encryption::{ + elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey}, + pedersen::H, + }, + errors::ProofVerificationError, }, curve25519_dalek::traits::MultiscalarMul, rand::rngs::OsRng, @@ -117,8 +120,14 @@ impl ZeroBalanceProof { let w_negated = -&w; // decompress Y or return verification error - let Y_P = self.Y_P.decompress().ok_or(ZeroBalanceProofError::Format)?; - let Y_D = self.Y_D.decompress().ok_or(ZeroBalanceProofError::Format)?; + let Y_P = self + .Y_P + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; + let Y_D = self + .Y_D + .decompress() + .ok_or(ProofVerificationError::Deserialization)?; // check the required algebraic relation let check = RistrettoPoint::multiscalar_mul( @@ -143,7 +152,7 @@ impl ZeroBalanceProof { if check.is_identity() { Ok(()) } else { - Err(ZeroBalanceProofError::AlgebraicRelation) + Err(ProofVerificationError::AlgebraicRelation.into()) } } @@ -157,7 +166,7 @@ impl ZeroBalanceProof { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 96 { - return Err(ZeroBalanceProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let bytes = array_ref![bytes, 0, 96]; @@ -166,7 +175,7 @@ impl ZeroBalanceProof { let Y_P = CompressedRistretto::from_slice(Y_P); let Y_D = CompressedRistretto::from_slice(Y_D); - let z = Scalar::from_canonical_bytes(*z).ok_or(ZeroBalanceProofError::Format)?; + let z = Scalar::from_canonical_bytes(*z).ok_or(ProofVerificationError::Deserialization)?; Ok(ZeroBalanceProof { Y_P, Y_D, z }) } diff --git a/zk-token-sdk/src/zk_token_elgamal/convert.rs b/zk-token-sdk/src/zk_token_elgamal/convert.rs index 108bc4aca..a327b3f2d 100644 --- a/zk-token-sdk/src/zk_token_elgamal/convert.rs +++ b/zk-token-sdk/src/zk_token_elgamal/convert.rs @@ -57,7 +57,7 @@ mod target_arch { elgamal::{DecryptHandle, ElGamalCiphertext, ElGamalPubkey}, pedersen::PedersenCommitment, }, - errors::ProofError, + errors::{ProofError, ProofVerificationError}, instruction::{ transfer::{TransferAmountEncryption, TransferPubkeys}, transfer_with_fee::{FeeEncryption, FeeParameters, TransferWithFeePubkeys}, @@ -282,7 +282,7 @@ mod target_arch { } impl TryFrom for PubkeySigmaProof { - type Error = PubkeySigmaProofError; + type Error = PubkeyValidityProofError; fn try_from(pod: pod::PubkeySigmaProof) -> Result { Self::from_bytes(&pod.0) @@ -294,7 +294,7 @@ mod target_arch { fn try_from(proof: RangeProof) -> Result { if proof.ipp_proof.serialized_size() != 448 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let mut buf = [0_u8; 672]; @@ -324,7 +324,7 @@ mod target_arch { fn try_from(proof: RangeProof) -> Result { if proof.ipp_proof.serialized_size() != 512 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let mut buf = [0_u8; 736]; @@ -354,7 +354,7 @@ mod target_arch { fn try_from(proof: RangeProof) -> Result { if proof.ipp_proof.serialized_size() != 576 { - return Err(RangeProofError::Format); + return Err(ProofVerificationError::Deserialization.into()); } let mut buf = [0_u8; 800];