Check statement correctness on compile (#104)

* Check statement correctness on compile

* format

* Update src/frontend/mod.rs

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* clean error handling

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* clean coding style

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* don't need to return ()

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* Update github workflow for mdbook

* Resolve issue from merge: pass params to check()

---------

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>
This commit is contained in:
tideofwords 2025-03-03 15:12:09 -08:00 committed by GitHub
parent c92839d897
commit 5092149f9f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 10 deletions

View file

@ -21,6 +21,7 @@ jobs:
run: | run: |
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh
rustup update rustup update
rustup toolchain install nightly-x86_64-unknown-linux-gnu
cargo install --version ${MDBOOK_VERSION} mdbook cargo install --version ${MDBOOK_VERSION} mdbook
cargo install --version ${MDBOOKKATEX_VERSION} mdbook-katex cargo install --version ${MDBOOKKATEX_VERSION} mdbook-katex
- name: Build with mdBook - name: Build with mdBook

View file

@ -507,7 +507,7 @@ pub mod tests {
zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod)?; zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod, &sanction_list_pod)?;
let mut prover = MockProver {}; let mut prover = MockProver {};
let kyc_pod = kyc_builder.prove(&mut prover)?; let kyc_pod = kyc_builder.prove(&mut prover, &params)?;
let pod = kyc_pod.pod.into_any().downcast::<MockMainPod>().unwrap(); let pod = kyc_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
println!("{:#}", pod); println!("{:#}", pod);
@ -520,10 +520,11 @@ pub mod tests {
#[test] #[test]
fn test_mock_main_great_boy() -> Result<()> { fn test_mock_main_great_boy() -> Result<()> {
let params = middleware::Params::default();
let great_boy_builder = great_boy_pod_full_flow()?; let great_boy_builder = great_boy_pod_full_flow()?;
let mut prover = MockProver {}; let mut prover = MockProver {};
let great_boy_pod = great_boy_builder.prove(&mut prover)?; let great_boy_pod = great_boy_builder.prove(&mut prover, &params)?;
let pod = great_boy_pod let pod = great_boy_pod
.pod .pod
.into_any() .into_any()
@ -539,9 +540,10 @@ pub mod tests {
#[test] #[test]
fn test_mock_main_tickets() -> Result<()> { fn test_mock_main_tickets() -> Result<()> {
let params = middleware::Params::default();
let tickets_builder = tickets_pod_full_flow()?; let tickets_builder = tickets_pod_full_flow()?;
let mut prover = MockProver {}; let mut prover = MockProver {};
let proof_pod = tickets_builder.prove(&mut prover)?; let proof_pod = tickets_builder.prove(&mut prover, &params)?;
let pod = proof_pod.pod.into_any().downcast::<MockMainPod>().unwrap(); let pod = proof_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
println!("{}", pod); println!("{}", pod);

View file

@ -1,7 +1,7 @@
//! The frontend includes the user-level abstractions and user-friendly types to define and work //! The frontend includes the user-level abstractions and user-friendly types to define and work
//! with Pods. //! with Pods.
use anyhow::Result; use anyhow::{anyhow, Error, Result};
use itertools::Itertools; use itertools::Itertools;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From; use std::convert::From;
@ -348,7 +348,7 @@ impl MainPodBuilder {
self.public_statements.push(st.clone()); self.public_statements.push(st.clone());
} }
pub fn prove<P: PodProver>(&self, prover: &mut P) -> Result<MainPod> { pub fn prove<P: PodProver>(&self, prover: &mut P, params: &Params) -> Result<MainPod> {
let compiler = MainPodCompiler::new(&self.params); let compiler = MainPodCompiler::new(&self.params);
let inputs = MainPodCompilerInputs { let inputs = MainPodCompilerInputs {
// signed_pods: &self.input_signed_pods, // signed_pods: &self.input_signed_pods,
@ -357,7 +357,7 @@ impl MainPodBuilder {
operations: &self.operations, operations: &self.operations,
public_statements: &self.public_statements, public_statements: &self.public_statements,
}; };
let (statements, operations, public_statements) = compiler.compile(inputs)?; let (statements, operations, public_statements) = compiler.compile(inputs, params)?;
let inputs = MainPodInputs { let inputs = MainPodInputs {
signed_pods: &self.input_signed_pods.iter().map(|p| &p.pod).collect_vec(), signed_pods: &self.input_signed_pods.iter().map(|p| &p.pod).collect_vec(),
@ -462,15 +462,27 @@ impl MainPodCompiler {
middleware::Operation::op(mop_code, &mop_args).unwrap() middleware::Operation::op(mop_code, &mop_args).unwrap()
} }
fn compile_st_op(&mut self, st: &Statement, op: &Operation) { fn compile_st_op(&mut self, st: &Statement, op: &Operation, params: &Params) -> Result<()> {
let middle_st = self.compile_st(st); let middle_st = self.compile_st(st);
let middle_op = self.compile_op(op); let middle_op = self.compile_op(op);
let is_correct = middle_op.check(params, &middle_st)?;
if !is_correct {
// todo: improve error handling
Err(anyhow!(
"Compile failed due to invalid deduction:\n {} ⇏ {}",
middle_op,
middle_st
))
} else {
self.push_st_op(middle_st, middle_op); self.push_st_op(middle_st, middle_op);
Ok(())
}
} }
pub fn compile<'a>( pub fn compile<'a>(
mut self, mut self,
inputs: MainPodCompilerInputs<'a>, inputs: MainPodCompilerInputs<'a>,
params: &Params,
) -> Result<( ) -> Result<(
Vec<middleware::Statement>, // input statements Vec<middleware::Statement>, // input statements
Vec<middleware::Operation>, Vec<middleware::Operation>,
@ -484,7 +496,7 @@ impl MainPodCompiler {
public_statements, public_statements,
} = inputs; } = inputs;
for (st, op) in statements.iter().zip_eq(operations.iter()) { for (st, op) in statements.iter().zip_eq(operations.iter()) {
self.compile_st_op(st, op); self.compile_st_op(st, op, params)?;
if self.statements.len() > self.params.max_statements { if self.statements.len() > self.params.max_statements {
panic!("too many statements"); panic!("too many statements");
} }
@ -570,7 +582,7 @@ pub mod tests {
println!("{}", kyc); println!("{}", kyc);
let mut prover = MockProver {}; let mut prover = MockProver {};
let kyc = kyc.prove(&mut prover)?; let kyc = kyc.prove(&mut prover, &params)?;
// TODO: prove kyc with MockProver and print it // TODO: prove kyc with MockProver and print it
println!("{}", kyc); println!("{}", kyc);
@ -595,4 +607,30 @@ pub mod tests {
Ok(()) Ok(())
} }
#[test]
#[should_panic]
fn test_false_st() {
let params = Params::default();
let mut builder = SignedPodBuilder::new(&params);
builder.insert("num", 2);
let mut signer = MockSigner {
pk: "signer".into(),
};
let pod = builder.sign(&mut signer).unwrap();
println!("{}", pod);
let mut builder = MainPodBuilder::new(&params);
builder.add_signed_pod(&pod);
builder.pub_op(op!(gt, (&pod, "num"), 5));
let mut prover = MockProver {};
let false_pod = builder.prove(&mut prover, &params).unwrap();
println!("{}", builder);
println!("{}", false_pod);
}
} }

View file

@ -1,4 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -265,3 +266,14 @@ impl Operation {
} }
} }
} }
impl fmt::Display for Operation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "middleware::Operation:")?;
writeln!(f, " {:?} ", self.code())?;
for (i, arg) in self.args().iter().enumerate() {
writeln!(f, " {}", arg)?;
}
Ok(())
}
}