Skip to content
Merged
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dyn-clone = "1.0.18"
log = "0.4"
env_logger = "0.11"
lazy_static = "1.5.0"
thiserror = { version = "2.0.12" }
# enabled by features:
plonky2 = { git = "https://github.com/0xPolygonZero/plonky2", optional = true }
serde = "1.0.219"
Expand Down
4 changes: 2 additions & 2 deletions src/backends/plonky2/circuits/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use std::{array, iter};

use anyhow::Result;
use plonky2::{
field::{
extension::Extendable,
Expand All @@ -19,6 +18,7 @@ use plonky2::{
use crate::{
backends::plonky2::{
basetypes::D,
error::Result,
mainpod::{Operation, OperationArg, Statement},
primitives::merkletree::MerkleClaimAndProofTarget,
},
Expand Down Expand Up @@ -75,7 +75,7 @@ impl StatementArgTarget {
params: &Params,
arg: &StatementArg,
) -> Result<()> {
pw.set_target_arr(&self.elements, &arg.to_fields(params))
Ok(pw.set_target_arr(&self.elements, &arg.to_fields(params))?)
}

fn new(first: ValueTarget, second: ValueTarget) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion src/backends/plonky2/circuits/mainpod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use anyhow::Result;
use itertools::zip_eq;
use plonky2::{
hash::{hash_types::HashOutTarget, poseidon::PoseidonHash},
Expand All @@ -16,6 +15,7 @@ use crate::{
},
signedpod::{SignedPodVerifyGadget, SignedPodVerifyTarget},
},
error::Result,
mainpod,
primitives::merkletree::{
MerkleClaimAndProof, MerkleClaimAndProofTarget, MerkleProofGadget,
Expand Down
2 changes: 1 addition & 1 deletion src/backends/plonky2/circuits/signedpod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::iter;

use anyhow::Result;
use itertools::Itertools;
use plonky2::{
hash::hash_types::{HashOut, HashOutTarget},
Expand All @@ -15,6 +14,7 @@ use crate::{
backends::plonky2::{
basetypes::D,
circuits::common::{CircuitBuilderPod, StatementArgTarget, StatementTarget, ValueTarget},
error::Result,
primitives::{
merkletree::{
MerkleClaimAndProof, MerkleProofExistenceGadget, MerkleProofExistenceTarget,
Expand Down
93 changes: 93 additions & 0 deletions src/backends/plonky2/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use std::{backtrace::Backtrace, fmt::Debug};

use crate::middleware::{PodId, PodType, Value};

pub type Result<T, E = Error> = core::result::Result<T, E>;

#[derive(thiserror::Error, Debug)]
pub enum InnerError {
#[error("id does not match, expected {0}, found {1}")]
IdNotEqual(PodId, PodId),
#[error("type does not match, expected {0}, found {1}")]
TypeNotEqual(PodType, Value),

// POD related
#[error("invalid POD ID")]
PodIdInvalid,
#[error("verification failed: POD does not have type statement")]
NotTypeStatement,
#[error("repeated ValueOf")]
RepeatedValueOf,
#[error("Statement did not check")]
StatementNotCheck,
#[error("Key not found")]
KeyNotFound,

// Other
#[error("{0}")]
Custom(String),
}

#[derive(thiserror::Error)]
pub enum Error {
#[error("Inner: {inner}\n{backtrace}")]
Inner {
inner: Box<InnerError>,
backtrace: Box<Backtrace>,
},
#[error("anyhow::Error: {0}")]
Anyhow(#[from] anyhow::Error),
#[error("Plonky2 proof failed to verify: {0}")]
Plonky2ProofFail(anyhow::Error),
#[error("base64::DecodeError: {0}")]
Base64Decode(#[from] base64::DecodeError),
#[error(transparent)]
Tree(#[from] crate::backends::plonky2::primitives::merkletree::error::TreeError),
#[error(transparent)]
Middleware(#[from] crate::middleware::Error),
}

impl Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}

macro_rules! new {
($inner:expr) => {
Error::Inner {
inner: Box::new($inner),
backtrace: Box::new(Backtrace::capture()),
}
};
}
use InnerError::*;
impl Error {
pub(crate) fn custom(s: String) -> Self {
new!(Custom(s))
}
pub(crate) fn plonky2_proof_fail(e: anyhow::Error) -> Self {
Self::Plonky2ProofFail(e)
}
pub(crate) fn key_not_found() -> Self {
new!(KeyNotFound)
}
pub(crate) fn statement_not_check() -> Self {
new!(StatementNotCheck)
}
pub(crate) fn repeated_value_of() -> Self {
new!(RepeatedValueOf)
}
pub(crate) fn not_type_statement() -> Self {
new!(NotTypeStatement)
}
pub(crate) fn pod_id_invalid() -> Self {
new!(PodIdInvalid)
}
pub(crate) fn id_not_equal(expected: PodId, found: PodId) -> Self {
new!(IdNotEqual(expected, found))
}
pub(crate) fn type_not_equal(expected: PodType, found: Value) -> Self {
new!(TypeNotEqual(expected, found))
}
}
61 changes: 37 additions & 24 deletions src/backends/plonky2/mainpod/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ pub mod operation;
pub mod statement;
use std::any::Any;

use anyhow::{anyhow, Result};
use itertools::Itertools;
pub use operation::*;
use plonky2::{
Expand All @@ -19,12 +18,13 @@ use crate::{
backends::plonky2::{
basetypes::{C, D},
circuits::mainpod::{MainPodVerifyCircuit, MainPodVerifyInput},
error::{Error, Result},
primitives::merkletree::MerkleClaimAndProof,
signedpod::SignedPod,
},
middleware::{
self, AnchoredKey, Hash, MainPodInputs, NativeOperation, NonePod, OperationType, Params,
Pod, PodId, PodProver, PodType, StatementArg, ToFields, F, KEY_TYPE, SELF,
self, AnchoredKey, DynError, Hash, MainPodInputs, NativeOperation, NonePod, OperationType,
Params, Pod, PodId, PodProver, PodType, StatementArg, ToFields, F, KEY_TYPE, SELF,
},
};

Expand Down Expand Up @@ -70,11 +70,11 @@ pub(crate) fn extract_merkle_proofs(
})
.collect();
if merkle_proofs.len() > params.max_merkle_proofs {
return Err(anyhow!(
return Err(Error::custom(format!(
"The number of required Merkle proofs ({}) exceeds the maximum number ({}).",
merkle_proofs.len(),
params.max_merkle_proofs
));
)));
}
Ok(merkle_proofs)
}
Expand All @@ -90,10 +90,10 @@ fn find_op_arg(statements: &[Statement], op_arg: &middleware::Statement) -> Resu
(&middleware::Statement::try_from(s.clone()).ok()? == op_arg).then_some(i)
})
.map(OperationArg::Index)
.ok_or(anyhow!(
.ok_or(Error::custom(format!(
"Statement corresponding to op arg {} not found",
op_arg
)),
))),
}
}

Expand All @@ -109,10 +109,10 @@ fn find_op_aux(
.enumerate()
.find_map(|(i, pf)| (pf.proof == *pf_arg).then_some(i))
.map(OperationAux::MerkleProofIndex)
.ok_or(anyhow!(
.ok_or(Error::custom(format!(
"Merkle proof corresponding to op arg {} not found",
op_aux
)),
))),
}
}

Expand Down Expand Up @@ -279,8 +279,8 @@ pub(crate) fn process_public_statements_operations(

pub struct Prover {}

impl PodProver for Prover {
fn prove(&mut self, params: &Params, inputs: MainPodInputs) -> Result<Box<dyn Pod>> {
impl Prover {
fn _prove(&mut self, params: &Params, inputs: MainPodInputs) -> Result<MainPod> {
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let main_pod = MainPodVerifyCircuit {
Expand Down Expand Up @@ -328,12 +328,22 @@ impl PodProver for Prover {
let data = builder.build::<C>();
let proof = data.prove(pw)?;

Ok(Box::new(MainPod {
Ok(MainPod {
params: params.clone(),
id,
public_statements,
proof,
}))
})
}
}

impl PodProver for Prover {
fn prove(
&mut self,
params: &Params,
inputs: MainPodInputs,
) -> Result<Box<dyn Pod>, Box<DynError>> {
Ok(self._prove(params, inputs).map(Box::new)?)
}
}

Expand Down Expand Up @@ -364,16 +374,12 @@ pub(crate) fn normalize_statement(statement: &Statement, self_id: PodId) -> midd
.unwrap()
}

impl Pod for MainPod {
fn verify(&self) -> Result<()> {
impl MainPod {
fn _verify(&self) -> Result<()> {
// 2. get the id out of the public statements
let id: PodId = PodId(hash_statements(&self.public_statements, &self.params));
if id != self.id {
return Err(anyhow!(
"id does not match, expected {}, computed {}",
self.id,
id
));
return Err(Error::id_not_equal(self.id, id));
}

// 1, 3, 4, 5 verification via the zkSNARK proof
Expand All @@ -387,7 +393,13 @@ impl Pod for MainPod {

let data = builder.build::<C>();
data.verify(self.proof.clone())
.map_err(|e| anyhow!("MainPod proof verification failure: {:?}", e))
.map_err(|e| Error::custom(format!("MainPod proof verification failure: {:?}", e)))
}
}

impl Pod for MainPod {
fn verify(&self) -> Result<(), Box<DynError>> {
Ok(self._verify()?)
}

fn id(&self) -> PodId {
Expand Down Expand Up @@ -418,13 +430,14 @@ pub mod tests {
signedpod::Signer,
},
examples::{zu_kyc_pod_builder, zu_kyc_sign_pod_builders},
frontend, middleware,
frontend::{self},
middleware,
middleware::RawValue,
op,
};

#[test]
fn test_main_zu_kyc() -> Result<()> {
fn test_main_zu_kyc() -> frontend::Result<()> {
let params = middleware::Params {
// Currently the circuit uses random access that only supports vectors of length 64.
// With max_input_main_pods=3 we need random access to a vector of length 73.
Expand All @@ -447,7 +460,7 @@ pub mod tests {
let kyc_pod = kyc_builder.prove(&mut prover, &params)?;
let pod = (kyc_pod.pod as Box<dyn Any>).downcast::<MainPod>().unwrap();

pod.verify()
Ok(pod.verify()?)
}

#[test]
Expand Down
15 changes: 11 additions & 4 deletions src/backends/plonky2/mainpod/operation.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::fmt;

use anyhow::{anyhow, Result};
use plonky2::field::types::Field;
use serde::{Deserialize, Serialize};

use crate::{
backends::plonky2::{mainpod::Statement, primitives::merkletree::MerkleClaimAndProof},
backends::plonky2::{
error::{Error, Result},
mainpod::Statement,
primitives::merkletree::MerkleClaimAndProof,
},
middleware::{self, OperationType, Params, ToFields, F},
};

Expand Down Expand Up @@ -78,12 +81,16 @@ impl Operation {
OperationAux::MerkleProofIndex(i) => crate::middleware::OperationAux::MerkleProof(
merkle_proofs
.get(i)
.ok_or(anyhow!("Missing Merkle proof index {}", i))?
.ok_or(Error::custom(format!("Missing Merkle proof index {}", i)))?
.proof
.clone(),
),
};
middleware::Operation::op(self.0.clone(), &deref_args, &deref_aux)
Ok(middleware::Operation::op(
self.0.clone(),
&deref_args,
&deref_aux,
)?)
}
}

Expand Down
13 changes: 8 additions & 5 deletions src/backends/plonky2/mainpod/statement.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::fmt;

use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};

use crate::middleware::{
self, NativePredicate, Params, Predicate, StatementArg, ToFields, WildcardValue,
use crate::{
backends::plonky2::error::{Error, Result},
middleware::{self, NativePredicate, Params, Predicate, StatementArg, ToFields, WildcardValue},
};

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -36,7 +36,7 @@ impl ToFields for Statement {
}

impl TryFrom<Statement> for middleware::Statement {
type Error = anyhow::Error;
type Error = Error;
fn try_from(s: Statement) -> Result<Self> {
type S = middleware::Statement;
type NP = NativePredicate;
Expand Down Expand Up @@ -78,7 +78,10 @@ impl TryFrom<Statement> for middleware::Statement {
(NP::MaxOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
S::MaxOf(ak1, ak2, ak3)
}
_ => Err(anyhow!("Ill-formed statement expression {:?}", s))?,
_ => Err(Error::custom(format!(
"Ill-formed statement expression {:?}",
s
)))?,
},
Predicate::Custom(cpr) => {
let vs: Vec<WildcardValue> = proper_args
Expand Down
Loading
Loading