migrate from anyhow to thiserror (#197)
* migrate from anyhow to thiserror (#190). pending polish error msgs * Add backtrace and compartmentalize errors - Include backtraces in the errors we generate. To get this we can't just return a literal enum, because the backtrace requires a call. - Related to the previous point: add methods to create errors so we can include the backtrace conveniently without changing too much the syntax. So instead of `Err(Error::KeyNotFound(key))` (literal enum) it will be `Err(Error::key_not_found(key))` (method call) - Each error should be local to its scope, and each scope should only return its own error. - The merkle tree should return `TreeError` and not Error - The middleware should return `MiddlewareError` and not Error - With a global Error we can't easily include backend/frontend types in the error fields, so declare a `BackendError` and a `FrontendError` and follow the pattern from the previous point - The Pod traits should be able to return backend errors and will be used in the frontend; for that we change them to use trait object Error: `dyn std::error::Error` * fix error * apply suggestions from @arnaucube * rename XError and XResult to Error and Result * reorg signature * make frontend custom error more ergonomic * remove unnecessary feature --------- Co-authored-by: Eduard S. <eduardsanou@posteo.net>
This commit is contained in:
parent
58d3c6a236
commit
29545f03fc
31 changed files with 696 additions and 273 deletions
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
error::{Error, Result},
|
||||
mainpod::{
|
||||
extract_merkle_proofs, hash_statements, layout_statements, normalize_statement,
|
||||
process_private_statements_operations, process_public_statements_operations, Operation,
|
||||
|
|
@ -18,15 +18,19 @@ use crate::{
|
|||
primitives::merkletree::MerkleClaimAndProof,
|
||||
},
|
||||
middleware::{
|
||||
self, hash_str, AnchoredKey, MainPodInputs, NativePredicate, Params, Pod, PodId, PodProver,
|
||||
Predicate, StatementArg, KEY_TYPE, SELF,
|
||||
self, hash_str, AnchoredKey, DynError, MainPodInputs, NativePredicate, Params, Pod, PodId,
|
||||
PodProver, Predicate, StatementArg, KEY_TYPE, SELF,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct MockProver {}
|
||||
|
||||
impl PodProver for MockProver {
|
||||
fn prove(&mut self, params: &Params, inputs: MainPodInputs) -> Result<Box<dyn Pod>> {
|
||||
fn prove(
|
||||
&mut self,
|
||||
params: &Params,
|
||||
inputs: MainPodInputs,
|
||||
) -> Result<Box<dyn Pod>, Box<DynError>> {
|
||||
Ok(Box::new(MockMainPod::new(params, inputs)?))
|
||||
}
|
||||
}
|
||||
|
|
@ -177,10 +181,8 @@ impl MockMainPod {
|
|||
|
||||
Ok(pod)
|
||||
}
|
||||
}
|
||||
|
||||
impl Pod for MockMainPod {
|
||||
fn verify(&self) -> Result<()> {
|
||||
fn _verify(&self) -> Result<()> {
|
||||
// 1. TODO: Verify input pods
|
||||
|
||||
let input_statement_offset = self.offset_input_statements();
|
||||
|
|
@ -245,24 +247,28 @@ impl Pod for MockMainPod {
|
|||
.unwrap()
|
||||
.check_and_log(&self.params, &s.clone().try_into().unwrap())
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()
|
||||
.collect::<Result<Vec<_>, middleware::Error>>()
|
||||
.unwrap();
|
||||
if !ids_match {
|
||||
return Err(anyhow!("Verification failed: POD ID is incorrect."));
|
||||
return Err(Error::pod_id_invalid());
|
||||
}
|
||||
if !has_type_statement {
|
||||
return Err(anyhow!(
|
||||
"Verification failed: POD does not have type statement."
|
||||
));
|
||||
return Err(Error::not_type_statement());
|
||||
}
|
||||
if !value_ofs_unique {
|
||||
return Err(anyhow!("Verification failed: Repeated ValueOf"));
|
||||
return Err(Error::repeated_value_of());
|
||||
}
|
||||
if !statement_check.iter().all(|b| *b) {
|
||||
return Err(anyhow!("Verification failed: Statement did not check."));
|
||||
return Err(Error::statement_not_check());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Pod for MockMainPod {
|
||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
||||
Ok(self._verify()?)
|
||||
}
|
||||
fn id(&self) -> PodId {
|
||||
self.id
|
||||
}
|
||||
|
|
@ -293,11 +299,12 @@ pub mod tests {
|
|||
great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder,
|
||||
zu_kyc_sign_pod_builders,
|
||||
},
|
||||
frontend,
|
||||
middleware::{self},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_mock_main_zu_kyc() -> Result<()> {
|
||||
fn test_mock_main_zu_kyc() -> frontend::Result<()> {
|
||||
let params = middleware::Params::default();
|
||||
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
|
||||
zu_kyc_sign_pod_builders(¶ms);
|
||||
|
|
@ -331,7 +338,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_mock_main_great_boy() -> Result<()> {
|
||||
fn test_mock_main_great_boy() -> frontend::Result<()> {
|
||||
let params = middleware::Params::default();
|
||||
let great_boy_builder = great_boy_pod_full_flow()?;
|
||||
|
||||
|
|
@ -349,7 +356,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_mock_main_tickets() -> Result<()> {
|
||||
fn test_mock_main_tickets() -> frontend::Result<()> {
|
||||
let params = middleware::Params::default();
|
||||
let tickets_builder = tickets_pod_full_flow()?;
|
||||
let mut prover = MockProver {};
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
backends::plonky2::primitives::merkletree::MerkleTree,
|
||||
backends::plonky2::{
|
||||
error::{Error, Result},
|
||||
primitives::merkletree::MerkleTree,
|
||||
},
|
||||
constants::MAX_DEPTH,
|
||||
middleware::{
|
||||
containers::Dictionary, hash_str, AnchoredKey, Hash, Key, Params, Pod, PodId, PodSigner,
|
||||
PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE,
|
||||
containers::Dictionary, hash_str, AnchoredKey, DynError, Hash, Key, Params, Pod, PodId,
|
||||
PodSigner, PodType, RawValue, Statement, Value, KEY_SIGNER, KEY_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -22,8 +24,8 @@ impl MockSigner {
|
|||
}
|
||||
}
|
||||
|
||||
impl PodSigner for MockSigner {
|
||||
fn sign(&mut self, _params: &Params, kvs: &HashMap<Key, Value>) -> Result<Box<dyn Pod>> {
|
||||
impl MockSigner {
|
||||
fn _sign(&mut self, _params: &Params, kvs: &HashMap<Key, Value>) -> Result<MockSignedPod> {
|
||||
let mut kvs = kvs.clone();
|
||||
let pubkey = self.pubkey();
|
||||
kvs.insert(Key::from(KEY_SIGNER), Value::from(pubkey));
|
||||
|
|
@ -32,7 +34,17 @@ impl PodSigner for MockSigner {
|
|||
let dict = Dictionary::new(kvs.clone())?;
|
||||
let id = PodId(dict.commitment());
|
||||
let signature = format!("{}_signed_by_{}", id, pubkey);
|
||||
Ok(Box::new(MockSignedPod { id, signature, kvs }))
|
||||
Ok(MockSignedPod { id, signature, kvs })
|
||||
}
|
||||
}
|
||||
|
||||
impl PodSigner for MockSigner {
|
||||
fn sign(
|
||||
&mut self,
|
||||
params: &Params,
|
||||
kvs: &HashMap<Key, Value>,
|
||||
) -> Result<Box<dyn Pod>, Box<DynError>> {
|
||||
Ok(self._sign(params, kvs).map(Box::new)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,8 +61,8 @@ impl MockSignedPod {
|
|||
}
|
||||
}
|
||||
|
||||
impl Pod for MockSignedPod {
|
||||
fn verify(&self) -> Result<()> {
|
||||
impl MockSignedPod {
|
||||
fn _verify(&self) -> Result<()> {
|
||||
// 1. Verify id
|
||||
let mt = MerkleTree::new(
|
||||
MAX_DEPTH,
|
||||
|
|
@ -62,23 +74,18 @@ impl Pod for MockSignedPod {
|
|||
)?;
|
||||
let id = PodId(mt.root());
|
||||
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));
|
||||
}
|
||||
|
||||
// 2. Verify type
|
||||
let value_at_type = self
|
||||
.kvs
|
||||
.get(&Key::from(KEY_TYPE))
|
||||
.ok_or(anyhow!("key not found"))?;
|
||||
.ok_or(Error::key_not_found())?;
|
||||
if &Value::from(PodType::MockSigned) != value_at_type {
|
||||
return Err(anyhow!(
|
||||
"type does not match, expected MockSigned ({}), found {}",
|
||||
return Err(Error::type_not_equal(
|
||||
PodType::MockSigned,
|
||||
value_at_type
|
||||
value_at_type.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -86,18 +93,23 @@ impl Pod for MockSignedPod {
|
|||
let pk_hash = self
|
||||
.kvs
|
||||
.get(&Key::from(KEY_SIGNER))
|
||||
.ok_or(anyhow!("key not found"))?;
|
||||
.ok_or(Error::key_not_found())?;
|
||||
let signature = format!("{}_signed_by_{}", id, pk_hash);
|
||||
if signature != self.signature {
|
||||
return Err(anyhow!(
|
||||
return Err(Error::custom(format!(
|
||||
"signature does not match, expected {}, computed {}",
|
||||
self.id,
|
||||
id
|
||||
));
|
||||
self.id, id
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Pod for MockSignedPod {
|
||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
||||
Ok(self._verify()?)
|
||||
}
|
||||
|
||||
fn id(&self) -> PodId {
|
||||
self.id
|
||||
|
|
@ -149,7 +161,7 @@ pub mod tests {
|
|||
.downcast::<MockSignedPod>()
|
||||
.unwrap();
|
||||
|
||||
pod.verify()?;
|
||||
pod._verify()?;
|
||||
println!("id: {}", pod.id());
|
||||
println!("kvs: {:?}", pod.kvs());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue