[zk-token-sdk] reorganize errors (#29005)
* reorganize error using DRY principle * rename error `Format` to `Deserialization` * Rename `EncryptionError` to `DiscreteLogError` * resolve errors from rebase * resolve clippy * change `ProofInstructionError` to `ProofError`
This commit is contained in:
parent
f766895f78
commit
ae57a14ef6
|
@ -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;
|
||||
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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<RangeProofError> for ProofError {
|
||||
fn from(_err: RangeProofError) -> Self {
|
||||
Self::RangeProof
|
||||
fn from(err: RangeProofError) -> Self {
|
||||
Self::VerificationError(ProofType::RangeProof, err.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EqualityProofError> for ProofError {
|
||||
fn from(_err: EqualityProofError) -> Self {
|
||||
Self::EqualityProof
|
||||
fn from(err: EqualityProofError) -> Self {
|
||||
Self::VerificationError(ProofType::EqualityProof, err.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FeeSigmaProofError> for ProofError {
|
||||
fn from(_err: FeeSigmaProofError) -> Self {
|
||||
Self::FeeProof
|
||||
fn from(err: FeeSigmaProofError) -> Self {
|
||||
Self::VerificationError(ProofType::FeeSigmaProof, err.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ZeroBalanceProofError> for ProofError {
|
||||
fn from(_err: ZeroBalanceProofError) -> Self {
|
||||
Self::ZeroBalanceProof
|
||||
fn from(err: ZeroBalanceProofError) -> Self {
|
||||
Self::VerificationError(ProofType::ZeroBalanceProof, err.0)
|
||||
}
|
||||
}
|
||||
impl From<ValidityProofError> for ProofError {
|
||||
fn from(_err: ValidityProofError) -> Self {
|
||||
Self::ValidityProof
|
||||
fn from(err: ValidityProofError) -> Self {
|
||||
Self::VerificationError(ProofType::ValidityProof, err.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PubkeySigmaProofError> for ProofError {
|
||||
fn from(_err: PubkeySigmaProofError) -> Self {
|
||||
Self::PubkeySigmaProof
|
||||
impl From<PubkeyValidityProofError> for ProofError {
|
||||
fn from(err: PubkeyValidityProofError) -> Self {
|
||||
Self::VerificationError(ProofType::PubkeyValidityProof, err.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -74,3 +74,13 @@ macro_rules! define_mul_variants {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_transcript_error {
|
||||
($sigma_error_type:ty) => {
|
||||
impl From<TranscriptError> for $sigma_error_type {
|
||||
fn from(err: TranscriptError) -> Self {
|
||||
ProofVerificationError::Transcript(err).into()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<TranscriptError> 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);
|
||||
|
|
|
@ -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<<lg_n below.
|
||||
return Err(RangeProofError::InvalidBitsize);
|
||||
return Err(ProofVerificationError::InvalidBitSize.into());
|
||||
}
|
||||
if n != (1 << lg_n) {
|
||||
return Err(RangeProofError::InvalidBitsize);
|
||||
return Err(ProofVerificationError::InvalidBitSize.into());
|
||||
}
|
||||
|
||||
transcript.innerproduct_domain_sep(n as u64);
|
||||
|
@ -298,13 +299,19 @@ impl InnerProductProof {
|
|||
let Ls = self
|
||||
.L_vec
|
||||
.iter()
|
||||
.map(|p| p.decompress().ok_or(RangeProofError::Format))
|
||||
.map(|p| {
|
||||
p.decompress()
|
||||
.ok_or(ProofVerificationError::Deserialization)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let Rs = self
|
||||
.R_vec
|
||||
.iter()
|
||||
.map(|p| p.decompress().ok_or(RangeProofError::Format))
|
||||
.map(|p| {
|
||||
p.decompress()
|
||||
.ok_or(ProofVerificationError::Deserialization)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
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<InnerProductProof, RangeProofError> {
|
||||
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<CompressedRistretto> = 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 })
|
||||
}
|
||||
|
|
|
@ -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<RangeProof, RangeProofError> {
|
||||
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..])?;
|
||||
|
||||
|
|
|
@ -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<Self, EqualityProofError> {
|
||||
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<Self, EqualityProofError> {
|
||||
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,
|
||||
|
|
|
@ -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<TranscriptError> 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<TranscriptError> 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<TranscriptError> 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<TranscriptError> 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<TranscriptError> 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);
|
||||
|
|
|
@ -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<Self, FeeSigmaProofError> {
|
||||
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 {
|
||||
|
|
|
@ -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<Self, PubkeySigmaProofError> {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, PubkeyValidityProofError> {
|
||||
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 })
|
||||
}
|
||||
|
|
|
@ -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<Self, ValidityProofError> {
|
||||
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,
|
||||
|
|
|
@ -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<Self, ZeroBalanceProofError> {
|
||||
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 })
|
||||
}
|
||||
|
|
|
@ -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<pod::PubkeySigmaProof> for PubkeySigmaProof {
|
||||
type Error = PubkeySigmaProofError;
|
||||
type Error = PubkeyValidityProofError;
|
||||
|
||||
fn try_from(pod: pod::PubkeySigmaProof) -> Result<Self, Self::Error> {
|
||||
Self::from_bytes(&pod.0)
|
||||
|
@ -294,7 +294,7 @@ mod target_arch {
|
|||
|
||||
fn try_from(proof: RangeProof) -> Result<Self, Self::Error> {
|
||||
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<Self, Self::Error> {
|
||||
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<Self, Self::Error> {
|
||||
if proof.ipp_proof.serialized_size() != 576 {
|
||||
return Err(RangeProofError::Format);
|
||||
return Err(ProofVerificationError::Deserialization.into());
|
||||
}
|
||||
|
||||
let mut buf = [0_u8; 800];
|
||||
|
|
Loading…
Reference in New Issue