feat: add separate error types for sigma proofs
This commit is contained in:
parent
7439d2424b
commit
1cbcda71cb
|
@ -1,10 +1,15 @@
|
||||||
//! Errors related to proving and verifying proofs.
|
//! Errors related to proving and verifying proofs.
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use crate::range_proof::errors::RangeProofError;
|
||||||
|
|
||||||
#[derive(Error, Clone, Debug, Eq, PartialEq)]
|
#[derive(Error, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum ProofError {
|
pub enum ProofError {
|
||||||
#[error("proof failed to verify")]
|
#[error("proof failed to verify")]
|
||||||
VerificationError,
|
VerificationError,
|
||||||
|
#[error("range proof failed to verify")]
|
||||||
|
RangeProofError,
|
||||||
|
#[error("sigma proof failed to verify")]
|
||||||
|
SigmaProofError,
|
||||||
#[error(
|
#[error(
|
||||||
"`zk_token_elgamal::pod::ElGamalCiphertext` contains invalid ElGamalCiphertext ciphertext"
|
"`zk_token_elgamal::pod::ElGamalCiphertext` contains invalid ElGamalCiphertext ciphertext"
|
||||||
)]
|
)]
|
||||||
|
@ -16,3 +21,9 @@ pub enum TranscriptError {
|
||||||
#[error("point is the identity")]
|
#[error("point is the identity")]
|
||||||
ValidationError,
|
ValidationError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RangeProofError> for ProofError {
|
||||||
|
fn from(err: RangeProofError) -> Self {
|
||||||
|
Self::RangeProofError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -266,7 +266,7 @@ impl TransferProof {
|
||||||
ValidityProof::new(dest_pk, auditor_pk, transfer_amt, openings, &mut transcript);
|
ValidityProof::new(dest_pk, auditor_pk, transfer_amt, openings, &mut transcript);
|
||||||
|
|
||||||
// generate the range proof
|
// generate the range proof
|
||||||
let range_proof = RangeProof::create(
|
let range_proof = RangeProof::new(
|
||||||
vec![source_new_balance, transfer_amt.0, transfer_amt.1],
|
vec![source_new_balance, transfer_amt.0, transfer_amt.1],
|
||||||
vec![64, 32, 32],
|
vec![64, 32, 32],
|
||||||
vec![&source_open, openings.0, openings.1],
|
vec![&source_open, openings.0, openings.1],
|
||||||
|
|
|
@ -136,7 +136,7 @@ impl WithdrawProof {
|
||||||
&mut transcript,
|
&mut transcript,
|
||||||
);
|
);
|
||||||
|
|
||||||
let range_proof = RangeProof::create(
|
let range_proof = RangeProof::new(
|
||||||
vec![final_balance],
|
vec![final_balance],
|
||||||
vec![64],
|
vec![64],
|
||||||
vec![&opening],
|
vec![&opening],
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Errors related to proving and verifying proofs.
|
//! Errors related to proving and verifying range proofs.
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use crate::errors::TranscriptError;
|
use crate::errors::TranscriptError;
|
||||||
|
|
||||||
|
@ -8,10 +8,12 @@ pub enum RangeProofError {
|
||||||
AlgebraicRelationError,
|
AlgebraicRelationError,
|
||||||
#[error("malformed proof")]
|
#[error("malformed proof")]
|
||||||
FormatError,
|
FormatError,
|
||||||
#[error("attempted to create a proof with a non-power-of-two bitsize")]
|
#[error("attempted to create a proof with a non-power-of-two bitsize or bitsize too big")]
|
||||||
InvalidBitsize,
|
InvalidBitsize,
|
||||||
#[error("insufficient generators for the proof")]
|
#[error("insufficient generators for the proof")]
|
||||||
InvalidGeneratorsLength,
|
InvalidGeneratorsLength,
|
||||||
|
#[error("multiscalar multiplication failed")]
|
||||||
|
MultiscalarMulError,
|
||||||
#[error("transcript failed to produce a challenge")]
|
#[error("transcript failed to produce a challenge")]
|
||||||
TranscriptError,
|
TranscriptError,
|
||||||
#[error("number of blinding factors do not match the number of values")]
|
#[error("number of blinding factors do not match the number of values")]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::{errors::ProofError, range_proof::util, transcript::TranscriptProtocol},
|
crate::{range_proof::{errors::RangeProofError, util}, transcript::TranscriptProtocol},
|
||||||
core::iter,
|
core::iter,
|
||||||
curve25519_dalek::{
|
curve25519_dalek::{
|
||||||
ristretto::{CompressedRistretto, RistrettoPoint},
|
ristretto::{CompressedRistretto, RistrettoPoint},
|
||||||
|
@ -200,15 +200,15 @@ impl InnerProductProof {
|
||||||
&self,
|
&self,
|
||||||
n: usize,
|
n: usize,
|
||||||
transcript: &mut Transcript,
|
transcript: &mut Transcript,
|
||||||
) -> Result<(Vec<Scalar>, Vec<Scalar>, Vec<Scalar>), ProofError> {
|
) -> Result<(Vec<Scalar>, Vec<Scalar>, Vec<Scalar>), RangeProofError> {
|
||||||
let lg_n = self.L_vec.len();
|
let lg_n = self.L_vec.len();
|
||||||
if lg_n >= 32 {
|
if lg_n >= 32 {
|
||||||
// 4 billion multiplications should be enough for anyone
|
// 4 billion multiplications should be enough for anyone
|
||||||
// and this check prevents overflow in 1<<lg_n below.
|
// and this check prevents overflow in 1<<lg_n below.
|
||||||
return Err(ProofError::VerificationError);
|
return Err(RangeProofError::InvalidBitsize);
|
||||||
}
|
}
|
||||||
if n != (1 << lg_n) {
|
if n != (1 << lg_n) {
|
||||||
return Err(ProofError::VerificationError);
|
return Err(RangeProofError::InvalidBitsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
transcript.innerproduct_domain_sep(n as u64);
|
transcript.innerproduct_domain_sep(n as u64);
|
||||||
|
@ -266,7 +266,7 @@ impl InnerProductProof {
|
||||||
G: &[RistrettoPoint],
|
G: &[RistrettoPoint],
|
||||||
H: &[RistrettoPoint],
|
H: &[RistrettoPoint],
|
||||||
transcript: &mut Transcript,
|
transcript: &mut Transcript,
|
||||||
) -> Result<(), ProofError>
|
) -> Result<(), RangeProofError>
|
||||||
where
|
where
|
||||||
IG: IntoIterator,
|
IG: IntoIterator,
|
||||||
IG::Item: Borrow<Scalar>,
|
IG::Item: Borrow<Scalar>,
|
||||||
|
@ -295,13 +295,13 @@ impl InnerProductProof {
|
||||||
let Ls = self
|
let Ls = self
|
||||||
.L_vec
|
.L_vec
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.decompress().ok_or(ProofError::VerificationError))
|
.map(|p| p.decompress().ok_or(RangeProofError::FormatError))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let Rs = self
|
let Rs = self
|
||||||
.R_vec
|
.R_vec
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.decompress().ok_or(ProofError::VerificationError))
|
.map(|p| p.decompress().ok_or(RangeProofError::FormatError))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let expect_P = RistrettoPoint::vartime_multiscalar_mul(
|
let expect_P = RistrettoPoint::vartime_multiscalar_mul(
|
||||||
|
@ -320,7 +320,7 @@ impl InnerProductProof {
|
||||||
if expect_P == *P {
|
if expect_P == *P {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ProofError::VerificationError)
|
Err(RangeProofError::AlgebraicRelationError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,55 +348,27 @@ impl InnerProductProof {
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn to_bytes_64(&self) -> Result<InnerProductProof64, ProofError> {
|
|
||||||
// let mut bytes = [0u8; 448];
|
|
||||||
|
|
||||||
// self.L_vec.iter().chain(self.R_vec.iter()).enumerate().for_each(
|
|
||||||
// |(i, x)| bytes[i*32..(i+1)*32].copy_from_slice(x.as_bytes())
|
|
||||||
// );
|
|
||||||
// bytes[384..416].copy_from_slice(self.a.as_bytes());
|
|
||||||
// bytes[416..448].copy_from_slice(self.a.as_bytes());
|
|
||||||
// Ok(InnerProductProof64(bytes))
|
|
||||||
// }
|
|
||||||
|
|
||||||
/*
|
|
||||||
/// Converts the proof into a byte iterator over serialized view of the proof.
|
|
||||||
/// The layout of the inner product proof is:
|
|
||||||
/// * \\(n\\) pairs of compressed Ristretto points \\(L_0, R_0 \dots, L_{n-1}, R_{n-1}\\),
|
|
||||||
/// * two scalars \\(a, b\\).
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn to_bytes_iter(&self) -> impl Iterator<Item = u8> + '_ {
|
|
||||||
self.L_vec
|
|
||||||
.iter()
|
|
||||||
.zip(self.R_vec.iter())
|
|
||||||
.flat_map(|(l, r)| l.as_bytes().iter().chain(r.as_bytes()))
|
|
||||||
.chain(self.a.as_bytes())
|
|
||||||
.chain(self.b.as_bytes())
|
|
||||||
.copied()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Deserializes the proof from a byte slice.
|
/// Deserializes the proof from a byte slice.
|
||||||
/// Returns an error in the following cases:
|
/// Returns an error in the following cases:
|
||||||
/// * the slice does not have \\(2n+2\\) 32-byte elements,
|
/// * the slice does not have \\(2n+2\\) 32-byte elements,
|
||||||
/// * \\(n\\) is larger or equal to 32 (proof is too big),
|
/// * \\(n\\) is larger or equal to 32 (proof is too big),
|
||||||
/// * any of \\(2n\\) points are not valid compressed Ristretto points,
|
/// * any of \\(2n\\) points are not valid compressed Ristretto points,
|
||||||
/// * any of 2 scalars are not canonical scalars modulo Ristretto group order.
|
/// * any of 2 scalars are not canonical scalars modulo Ristretto group order.
|
||||||
pub fn from_bytes(slice: &[u8]) -> Result<InnerProductProof, ProofError> {
|
pub fn from_bytes(slice: &[u8]) -> Result<InnerProductProof, RangeProofError> {
|
||||||
let b = slice.len();
|
let b = slice.len();
|
||||||
if b % 32 != 0 {
|
if b % 32 != 0 {
|
||||||
return Err(ProofError::FormatError);
|
return Err(RangeProofError::FormatError);
|
||||||
}
|
}
|
||||||
let num_elements = b / 32;
|
let num_elements = b / 32;
|
||||||
if num_elements < 2 {
|
if num_elements < 2 {
|
||||||
return Err(ProofError::FormatError);
|
return Err(RangeProofError::FormatError);
|
||||||
}
|
}
|
||||||
if (num_elements - 2) % 2 != 0 {
|
if (num_elements - 2) % 2 != 0 {
|
||||||
return Err(ProofError::FormatError);
|
return Err(RangeProofError::FormatError);
|
||||||
}
|
}
|
||||||
let lg_n = (num_elements - 2) / 2;
|
let lg_n = (num_elements - 2) / 2;
|
||||||
if lg_n >= 32 {
|
if lg_n >= 32 {
|
||||||
return Err(ProofError::FormatError);
|
return Err(RangeProofError::FormatError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut L_vec: Vec<CompressedRistretto> = Vec::with_capacity(lg_n);
|
let mut L_vec: Vec<CompressedRistretto> = Vec::with_capacity(lg_n);
|
||||||
|
@ -409,9 +381,9 @@ impl InnerProductProof {
|
||||||
|
|
||||||
let pos = 2 * lg_n * 32;
|
let pos = 2 * lg_n * 32;
|
||||||
let a = Scalar::from_canonical_bytes(util::read32(&slice[pos..]))
|
let a = Scalar::from_canonical_bytes(util::read32(&slice[pos..]))
|
||||||
.ok_or(ProofError::FormatError)?;
|
.ok_or(RangeProofError::FormatError)?;
|
||||||
let b = Scalar::from_canonical_bytes(util::read32(&slice[pos + 32..]))
|
let b = Scalar::from_canonical_bytes(util::read32(&slice[pos + 32..]))
|
||||||
.ok_or(ProofError::FormatError)?;
|
.ok_or(RangeProofError::FormatError)?;
|
||||||
|
|
||||||
Ok(InnerProductProof { L_vec, R_vec, a, b })
|
Ok(InnerProductProof { L_vec, R_vec, a, b })
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ impl RangeProof {
|
||||||
assert!(nm.is_power_of_two());
|
assert!(nm.is_power_of_two());
|
||||||
|
|
||||||
// TODO: precompute generators
|
// TODO: precompute generators
|
||||||
|
// TODO: double check Pedersen generators and range proof generators does not interfere
|
||||||
let bp_gens = BulletproofGens::new(nm);
|
let bp_gens = BulletproofGens::new(nm);
|
||||||
let G = PedersenBase::default().G;
|
let G = PedersenBase::default().G;
|
||||||
let H = PedersenBase::default().H;
|
let H = PedersenBase::default().H;
|
||||||
|
@ -222,6 +223,9 @@ impl RangeProof {
|
||||||
bit_lengths: Vec<usize>,
|
bit_lengths: Vec<usize>,
|
||||||
transcript: &mut Transcript,
|
transcript: &mut Transcript,
|
||||||
) -> Result<(), RangeProofError> {
|
) -> Result<(), RangeProofError> {
|
||||||
|
// commitments and bit-lengths must be same length vectors
|
||||||
|
assert_eq!(comms.len(), bit_lengths.len());
|
||||||
|
|
||||||
let G = PedersenBase::default().G;
|
let G = PedersenBase::default().G;
|
||||||
let H = PedersenBase::default().H;
|
let H = PedersenBase::default().H;
|
||||||
|
|
||||||
|
@ -233,6 +237,7 @@ impl RangeProof {
|
||||||
return Err(RangeProofError::InvalidBitsize);
|
return Err(RangeProofError::InvalidBitsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append proof data to transcript and derive appropriate challenge scalars
|
||||||
transcript.validate_and_append_point(b"A", &self.A)?;
|
transcript.validate_and_append_point(b"A", &self.A)?;
|
||||||
transcript.validate_and_append_point(b"S", &self.S)?;
|
transcript.validate_and_append_point(b"S", &self.S)?;
|
||||||
|
|
||||||
|
@ -252,17 +257,16 @@ impl RangeProof {
|
||||||
transcript.append_scalar(b"e_blinding", &self.e_blinding);
|
transcript.append_scalar(b"e_blinding", &self.e_blinding);
|
||||||
|
|
||||||
let w = transcript.challenge_scalar(b"w");
|
let w = transcript.challenge_scalar(b"w");
|
||||||
|
let c = transcript.challenge_scalar(b"c"); // challenge value for batching multiscalar mul
|
||||||
|
|
||||||
// Challenge value for batching statements to be verified
|
// verify inner product proof
|
||||||
let c = transcript.challenge_scalar(b"c");
|
|
||||||
|
|
||||||
let (x_sq, x_inv_sq, s) = self.ipp_proof.verification_scalars(nm, transcript)?;
|
let (x_sq, x_inv_sq, s) = self.ipp_proof.verification_scalars(nm, transcript)?;
|
||||||
let s_inv = s.iter().rev();
|
let s_inv = s.iter().rev();
|
||||||
|
|
||||||
let a = self.ipp_proof.a;
|
let a = self.ipp_proof.a;
|
||||||
let b = self.ipp_proof.b;
|
let b = self.ipp_proof.b;
|
||||||
|
|
||||||
// Construct concat_z_and_2, an iterator of the values of
|
// construct concat_z_and_2, an iterator of the values of
|
||||||
// z^0 * \vec(2)^n || z^1 * \vec(2)^n || ... || z^(m-1) * \vec(2)^n
|
// z^0 * \vec(2)^n || z^1 * \vec(2)^n || ... || z^(m-1) * \vec(2)^n
|
||||||
let concat_z_and_2: Vec<Scalar> = util::exp_iter(z)
|
let concat_z_and_2: Vec<Scalar> = util::exp_iter(z)
|
||||||
.zip(bit_lengths.iter())
|
.zip(bit_lengths.iter())
|
||||||
|
@ -308,12 +312,12 @@ impl RangeProof {
|
||||||
.chain(bp_gens.H(nm).map(|&x| Some(x)))
|
.chain(bp_gens.H(nm).map(|&x| Some(x)))
|
||||||
.chain(comms.iter().map(|V| V.decompress())),
|
.chain(comms.iter().map(|V| V.decompress())),
|
||||||
)
|
)
|
||||||
.ok_or(ProofError::VerificationError)?;
|
.ok_or(RangeProofError::MultiscalarMulError)?;
|
||||||
|
|
||||||
if mega_check.is_identity() {
|
if mega_check.is_identity() {
|
||||||
Ok((z, x))
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ProofError::VerificationError)
|
Err(RangeProofError::AlgebraicRelationError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,12 +338,12 @@ impl RangeProof {
|
||||||
|
|
||||||
// Following the dalek rangeproof library signature for now. The exact method signature can be
|
// Following the dalek rangeproof library signature for now. The exact method signature can be
|
||||||
// changed.
|
// changed.
|
||||||
pub fn from_bytes(slice: &[u8]) -> Result<RangeProof, ProofError> {
|
pub fn from_bytes(slice: &[u8]) -> Result<RangeProof, RangeProofError> {
|
||||||
if slice.len() % 32 != 0 {
|
if slice.len() % 32 != 0 {
|
||||||
return Err(ProofError::FormatError);
|
return Err(RangeProofError::FormatError);
|
||||||
}
|
}
|
||||||
if slice.len() < 7 * 32 {
|
if slice.len() < 7 * 32 {
|
||||||
return Err(ProofError::FormatError);
|
return Err(RangeProofError::FormatError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let A = CompressedRistretto(util::read32(&slice[0..]));
|
let A = CompressedRistretto(util::read32(&slice[0..]));
|
||||||
|
@ -348,11 +352,11 @@ impl RangeProof {
|
||||||
let T_2 = CompressedRistretto(util::read32(&slice[3 * 32..]));
|
let T_2 = CompressedRistretto(util::read32(&slice[3 * 32..]));
|
||||||
|
|
||||||
let t_x = Scalar::from_canonical_bytes(util::read32(&slice[4 * 32..]))
|
let t_x = Scalar::from_canonical_bytes(util::read32(&slice[4 * 32..]))
|
||||||
.ok_or(ProofError::FormatError)?;
|
.ok_or(RangeProofError::FormatError)?;
|
||||||
let t_x_blinding = Scalar::from_canonical_bytes(util::read32(&slice[5 * 32..]))
|
let t_x_blinding = Scalar::from_canonical_bytes(util::read32(&slice[5 * 32..]))
|
||||||
.ok_or(ProofError::FormatError)?;
|
.ok_or(RangeProofError::FormatError)?;
|
||||||
let e_blinding = Scalar::from_canonical_bytes(util::read32(&slice[6 * 32..]))
|
let e_blinding = Scalar::from_canonical_bytes(util::read32(&slice[6 * 32..]))
|
||||||
.ok_or(ProofError::FormatError)?;
|
.ok_or(RangeProofError::FormatError)?;
|
||||||
|
|
||||||
let ipp_proof = InnerProductProof::from_bytes(&slice[7 * 32..])?;
|
let ipp_proof = InnerProductProof::from_bytes(&slice[7 * 32..])?;
|
||||||
|
|
||||||
|
@ -398,7 +402,7 @@ mod tests {
|
||||||
let mut transcript_create = Transcript::new(b"Test");
|
let mut transcript_create = Transcript::new(b"Test");
|
||||||
let mut transcript_verify = Transcript::new(b"Test");
|
let mut transcript_verify = Transcript::new(b"Test");
|
||||||
|
|
||||||
let proof = RangeProof::create(vec![55], vec![32], vec![&open], &mut transcript_create);
|
let proof = RangeProof::new(vec![55], vec![32], vec![&open], &mut transcript_create);
|
||||||
|
|
||||||
assert!(proof
|
assert!(proof
|
||||||
.verify(
|
.verify(
|
||||||
|
@ -418,7 +422,7 @@ mod tests {
|
||||||
let mut transcript_create = Transcript::new(b"Test");
|
let mut transcript_create = Transcript::new(b"Test");
|
||||||
let mut transcript_verify = Transcript::new(b"Test");
|
let mut transcript_verify = Transcript::new(b"Test");
|
||||||
|
|
||||||
let proof = RangeProof::create(
|
let proof = RangeProof::new(
|
||||||
vec![55, 77, 99],
|
vec![55, 77, 99],
|
||||||
vec![64, 32, 32],
|
vec![64, 32, 32],
|
||||||
vec![&open_1, &open_2, &open_3],
|
vec![&open_1, &open_2, &open_3],
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
//! Errors related to proving and verifying sigma proofs.
|
||||||
|
use thiserror::Error;
|
||||||
|
use crate::errors::TranscriptError;
|
||||||
|
|
||||||
|
#[derive(Error, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum EqualityProof {
|
||||||
|
#[error("the required algebraic relation does not hold")]
|
||||||
|
AlgebraicRelationError,
|
||||||
|
#[error("malformed proof")]
|
||||||
|
FormatError,
|
||||||
|
#[error("multiscalar multiplication failed")]
|
||||||
|
MultiscalarMulError,
|
||||||
|
#[error("transcript failed to produce a challenge")]
|
||||||
|
TranscriptError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TranscriptError> for EqualityProof {
|
||||||
|
fn from(err: TranscriptError) -> Self {
|
||||||
|
Self::TranscriptError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum ValidityProof {
|
||||||
|
#[error("the required algebraic relation does not hold")]
|
||||||
|
AlgebraicRelationError,
|
||||||
|
#[error("malformed proof")]
|
||||||
|
FormatError,
|
||||||
|
#[error("multiscalar multiplication failed")]
|
||||||
|
MultiscalarMulError,
|
||||||
|
#[error("transcript failed to produce a challenge")]
|
||||||
|
TranscriptError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TranscriptError> for ValidityProof {
|
||||||
|
fn from(err: TranscriptError) -> Self {
|
||||||
|
Self::TranscriptError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum ZeroBalanceProof {
|
||||||
|
#[error("the required algebraic relation does not hold")]
|
||||||
|
AlgebraicRelationError,
|
||||||
|
#[error("malformed proof")]
|
||||||
|
FormatError,
|
||||||
|
#[error("multiscalar multiplication failed")]
|
||||||
|
MultiscalarMulError,
|
||||||
|
#[error("transcript failed to produce a challenge")]
|
||||||
|
TranscriptError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TranscriptError> for ZeroBalanceProof {
|
||||||
|
fn from(err: TranscriptError) -> Self {
|
||||||
|
Self::TranscriptError
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod equality_proof;
|
pub mod equality_proof;
|
||||||
|
pub mod errors;
|
||||||
pub mod fee_proof;
|
pub mod fee_proof;
|
||||||
pub mod validity_proof;
|
pub mod validity_proof;
|
||||||
pub mod zero_balance_proof;
|
pub mod zero_balance_proof;
|
||||||
|
|
Loading…
Reference in New Issue