Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[zk-token-sdk] Re-organize error types #34034

Merged
merged 8 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions zk-token-sdk/src/encryption/auth_encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub enum AuthenticatedEncryptionError {
SeedLengthTooShort,
#[error("seed length too long for derivation")]
SeedLengthTooLong,
#[error("failed to deserialize")]
Deserialization,
}

struct AuthenticatedEncryption;
Expand Down
4 changes: 4 additions & 0 deletions zk-token-sdk/src/encryption/elgamal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ pub enum ElGamalError {
SeedLengthTooShort,
#[error("seed length too long for derivation")]
SeedLengthTooLong,
#[error("failed to deserialize ciphertext")]
CiphertextDeserialization,
#[error("failed to deserialize public key")]
PubkeyDeserialization,
}

/// Algorithm handle for the twisted ElGamal encryption scheme
Expand Down
107 changes: 48 additions & 59 deletions zk-token-sdk/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,50 @@
//! Errors related to proving and verifying proofs.
use {
crate::{range_proof::errors::RangeProofError, sigma_proofs::errors::*},
crate::{
encryption::elgamal::ElGamalError,
range_proof::errors::{RangeProofGenerationError, RangeProofVerificationError},
sigma_proofs::errors::*,
},
thiserror::Error,
};

#[derive(Error, Clone, Debug, Eq, PartialEq)]
pub enum ProofError {
#[error("invalid transfer amount range")]
TransferAmount,
#[error("proof generation failed")]
Generation,
#[error("proof verification failed")]
VerificationError(ProofType, ProofVerificationError),
#[error("failed to decrypt ciphertext")]
Decryption,
#[error("invalid ciphertext data")]
CiphertextDeserialization,
#[error("invalid pubkey data")]
PubkeyDeserialization,
#[error("ciphertext does not exist in instruction data")]
MissingCiphertext,
pub enum ProofGenerationError {
#[error("not enough funds in account")]
NotEnoughFunds,
#[error("transfer fee calculation error")]
FeeCalculation,
#[error("illegal number of commitments")]
IllegalCommitmentLength,
#[error("illegal amount bit length")]
IllegalAmountBitLength,
#[error("invalid commitment")]
InvalidCommitment,
#[error("range proof generation failed")]
RangeProof(#[from] RangeProofGenerationError),
#[error("unexpected proof length")]
ProofLength,
}

#[derive(Error, Clone, Debug, Eq, PartialEq)]
pub enum ProofVerificationError {
#[error("range proof verification failed")]
RangeProof(#[from] RangeProofVerificationError),
#[error("sigma proof verification failed")]
SigmaProof(SigmaProofType, SigmaProofVerificationError),
#[error("ElGamal ciphertext or public key error")]
ElGamal(#[from] ElGamalError),
#[error("Invalid proof context")]
ProofContext,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProofType {
pub enum SigmaProofType {
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)]
Expand All @@ -58,37 +53,31 @@ pub enum TranscriptError {
ValidationError,
}

impl From<RangeProofError> for ProofError {
fn from(err: RangeProofError) -> Self {
Self::VerificationError(ProofType::RangeProof, err.0)
}
}

impl From<EqualityProofError> for ProofError {
fn from(err: EqualityProofError) -> Self {
Self::VerificationError(ProofType::EqualityProof, err.0)
impl From<EqualityProofVerificationError> for ProofVerificationError {
fn from(err: EqualityProofVerificationError) -> Self {
Self::SigmaProof(SigmaProofType::EqualityProof, err.0)
}
}

impl From<FeeSigmaProofError> for ProofError {
fn from(err: FeeSigmaProofError) -> Self {
Self::VerificationError(ProofType::FeeSigmaProof, err.0)
impl From<FeeSigmaProofVerificationError> for ProofVerificationError {
fn from(err: FeeSigmaProofVerificationError) -> Self {
Self::SigmaProof(SigmaProofType::FeeSigmaProof, err.0)
}
}

impl From<ZeroBalanceProofError> for ProofError {
fn from(err: ZeroBalanceProofError) -> Self {
Self::VerificationError(ProofType::ZeroBalanceProof, err.0)
impl From<ZeroBalanceProofVerificationError> for ProofVerificationError {
fn from(err: ZeroBalanceProofVerificationError) -> Self {
Self::SigmaProof(SigmaProofType::ZeroBalanceProof, err.0)
}
}
impl From<ValidityProofError> for ProofError {
fn from(err: ValidityProofError) -> Self {
Self::VerificationError(ProofType::ValidityProof, err.0)
impl From<ValidityProofVerificationError> for ProofVerificationError {
fn from(err: ValidityProofVerificationError) -> Self {
Self::SigmaProof(SigmaProofType::ValidityProof, err.0)
}
}

impl From<PubkeyValidityProofError> for ProofError {
fn from(err: PubkeyValidityProofError) -> Self {
Self::VerificationError(ProofType::PubkeyValidityProof, err.0)
impl From<PubkeyValidityProofVerificationError> for ProofVerificationError {
fn from(err: PubkeyValidityProofVerificationError) -> Self {
Self::SigmaProof(SigmaProofType::PubkeyValidityProof, err.0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use {
elgamal::ElGamalPubkey, grouped_elgamal::GroupedElGamalCiphertext,
pedersen::PedersenOpening,
},
errors::ProofError,
errors::{ProofGenerationError, ProofVerificationError},
sigma_proofs::batched_grouped_ciphertext_validity_proof::BatchedGroupedCiphertext2HandlesValidityProof,
transcript::TranscriptProtocol,
},
Expand Down Expand Up @@ -69,7 +69,7 @@ impl BatchedGroupedCiphertext2HandlesValidityProofData {
amount_hi: u64,
opening_lo: &PedersenOpening,
opening_hi: &PedersenOpening,
) -> Result<Self, ProofError> {
) -> Result<Self, ProofGenerationError> {
let pod_destination_pubkey = pod::ElGamalPubkey(destination_pubkey.to_bytes());
let pod_auditor_pubkey = pod::ElGamalPubkey(auditor_pubkey.to_bytes());
let pod_grouped_ciphertext_lo = (*grouped_ciphertext_lo).into();
Expand Down Expand Up @@ -106,7 +106,7 @@ impl ZkProofData<BatchedGroupedCiphertext2HandlesValidityProofContext>
}

#[cfg(not(target_os = "solana"))]
fn verify_proof(&self) -> Result<(), ProofError> {
fn verify_proof(&self) -> Result<(), ProofVerificationError> {
let mut transcript = self.context.new_transcript();

let destination_pubkey = self.context.destination_pubkey.try_into()?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use {
crate::{
encryption::pedersen::{PedersenCommitment, PedersenOpening},
errors::ProofError,
errors::{ProofGenerationError, ProofVerificationError},
range_proof::RangeProof,
},
std::convert::TryInto,
Expand Down Expand Up @@ -39,26 +39,29 @@ impl BatchedRangeProofU128Data {
amounts: Vec<u64>,
bit_lengths: Vec<usize>,
openings: Vec<&PedersenOpening>,
) -> Result<Self, ProofError> {
) -> Result<Self, ProofGenerationError> {
// the sum of the bit lengths must be 64
let batched_bit_length = bit_lengths
.iter()
.try_fold(0_usize, |acc, &x| acc.checked_add(x))
.ok_or(ProofError::Generation)?;
.ok_or(ProofGenerationError::IllegalAmountBitLength)?;

// `u64::BITS` is 128, which fits in a single byte and should not overflow to `usize` for
// an overwhelming number of platforms. However, to be extra cautious, use `try_from` and
// `unwrap` here. A simple case `u128::BITS as usize` can silently overflow.
let expected_bit_length = usize::try_from(u128::BITS).unwrap();
if batched_bit_length != expected_bit_length {
return Err(ProofError::Generation);
return Err(ProofGenerationError::IllegalAmountBitLength);
}

let context =
BatchedRangeProofContext::new(&commitments, &amounts, &bit_lengths, &openings)?;

let mut transcript = context.new_transcript();
let proof = RangeProof::new(amounts, bit_lengths, openings, &mut transcript).try_into()?;
let proof: pod::RangeProofU128 =
RangeProof::new(amounts, bit_lengths, openings, &mut transcript)?
.try_into()
.map_err(|_| ProofGenerationError::ProofLength)?;

Ok(Self { context, proof })
}
Expand All @@ -72,7 +75,7 @@ impl ZkProofData<BatchedRangeProofContext> for BatchedRangeProofU128Data {
}

#[cfg(not(target_os = "solana"))]
fn verify_proof(&self) -> Result<(), ProofError> {
fn verify_proof(&self) -> Result<(), ProofVerificationError> {
let (commitments, bit_lengths) = self.context.try_into()?;
let mut transcript = self.context_data().new_transcript();
let proof: RangeProof = self.proof.try_into()?;
Expand All @@ -88,8 +91,8 @@ mod test {
use {
super::*,
crate::{
encryption::pedersen::Pedersen,
errors::{ProofType, ProofVerificationError},
encryption::pedersen::Pedersen, errors::ProofVerificationError,
range_proof::errors::RangeProofVerificationError,
},
};

Expand Down Expand Up @@ -179,10 +182,7 @@ mod test {

assert_eq!(
proof_data.verify_proof().unwrap_err(),
ProofError::VerificationError(
ProofType::RangeProof,
ProofVerificationError::AlgebraicRelation
),
ProofVerificationError::RangeProof(RangeProofVerificationError::AlgebraicRelation),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use {
crate::{
encryption::pedersen::{PedersenCommitment, PedersenOpening},
errors::ProofError,
errors::{ProofGenerationError, ProofVerificationError},
range_proof::RangeProof,
},
std::convert::TryInto,
Expand Down Expand Up @@ -42,21 +42,23 @@ impl BatchedRangeProofU256Data {
amounts: Vec<u64>,
bit_lengths: Vec<usize>,
openings: Vec<&PedersenOpening>,
) -> Result<Self, ProofError> {
) -> Result<Self, ProofGenerationError> {
// the sum of the bit lengths must be 64
let batched_bit_length = bit_lengths
.iter()
.try_fold(0_usize, |acc, &x| acc.checked_add(x))
.ok_or(ProofError::Generation)?;
.ok_or(ProofGenerationError::IllegalAmountBitLength)?;
if batched_bit_length != BATCHED_RANGE_PROOF_U256_BIT_LENGTH {
return Err(ProofError::Generation);
return Err(ProofGenerationError::IllegalAmountBitLength);
}

let context =
BatchedRangeProofContext::new(&commitments, &amounts, &bit_lengths, &openings)?;

let mut transcript = context.new_transcript();
let proof = RangeProof::new(amounts, bit_lengths, openings, &mut transcript).try_into()?;
let proof = RangeProof::new(amounts, bit_lengths, openings, &mut transcript)?
.try_into()
.map_err(|_| ProofGenerationError::ProofLength)?;

Ok(Self { context, proof })
}
Expand All @@ -70,7 +72,7 @@ impl ZkProofData<BatchedRangeProofContext> for BatchedRangeProofU256Data {
}

#[cfg(not(target_os = "solana"))]
fn verify_proof(&self) -> Result<(), ProofError> {
fn verify_proof(&self) -> Result<(), ProofVerificationError> {
let (commitments, bit_lengths) = self.context.try_into()?;
let mut transcript = self.context_data().new_transcript();
let proof: RangeProof = self.proof.try_into()?;
Expand All @@ -86,8 +88,8 @@ mod test {
use {
super::*,
crate::{
encryption::pedersen::Pedersen,
errors::{ProofType, ProofVerificationError},
encryption::pedersen::Pedersen, errors::ProofVerificationError,
range_proof::errors::RangeProofVerificationError,
},
};

Expand Down Expand Up @@ -177,10 +179,7 @@ mod test {

assert_eq!(
proof_data.verify_proof().unwrap_err(),
ProofError::VerificationError(
ProofType::RangeProof,
ProofVerificationError::AlgebraicRelation
),
ProofVerificationError::RangeProof(RangeProofVerificationError::AlgebraicRelation),
);
}
}
Loading