Skip to content

Commit 2e9719a

Browse files
ed255arnaucube
andauthored
Prototype custom predicates (#74)
* wip * prototype custom predicates 1b * feat: implement custom pred recursion * files reorg, add github CI for rustfmt checks --------- Co-authored-by: arnaucube <git@arnaucube.com>
1 parent c2d23b0 commit 2e9719a

File tree

13 files changed

+528
-123
lines changed

13 files changed

+528
-123
lines changed

.github/workflows/rustfmt.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Rustfmt Check
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
types: [ready_for_review, opened, synchronize, reopened]
7+
push:
8+
branches: [ main ]
9+
10+
jobs:
11+
rustfmt:
12+
if: github.event.pull_request.draft == false
13+
name: Rust formatting
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions-rust-lang/setup-rust-toolchain@v1
18+
with:
19+
components: rustfmt
20+
- name: Check formatting
21+
uses: actions-rust-lang/rustfmt@v1

.github/workflows/typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[default.extend-words]
22
groth = "groth" # to avoid it dectecting it as 'growth'
3+
BA = "BA"
Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
mod operation;
2-
mod statement;
1+
use anyhow::{anyhow, Result};
2+
use itertools::Itertools;
3+
use plonky2::hash::poseidon::PoseidonHash;
4+
use plonky2::plonk::config::Hasher;
5+
use std::any::Any;
6+
use std::fmt;
37

48
use crate::middleware::{
5-
self, hash_str, AnchoredKey, Hash, MainPodInputs, NativeOperation, NativeStatement, NonePod,
9+
self, hash_str, AnchoredKey, Hash, MainPodInputs, NativeOperation, NativePredicate, NonePod,
610
Params, Pod, PodId, PodProver, StatementArg, ToFields, KEY_TYPE, SELF,
711
};
8-
use anyhow::Result;
9-
use itertools::Itertools;
12+
13+
mod operation;
14+
mod statement;
1015
pub use operation::*;
11-
use plonky2::hash::poseidon::PoseidonHash;
12-
use plonky2::plonk::config::Hasher;
1316
pub use statement::*;
14-
use std::any::Any;
15-
use std::fmt;
1617

1718
pub const VALUE_TYPE: &str = "MockMainPOD";
1819

@@ -222,26 +223,25 @@ impl MockMainPod {
222223
fn find_op_arg(
223224
statements: &[Statement],
224225
op_arg: &middleware::Statement,
225-
) -> Result<OperationArg, OperationArgError> {
226+
) -> Result<OperationArg> {
226227
match op_arg {
227228
middleware::Statement::None => Ok(OperationArg::None),
228229
_ => statements
229230
.iter()
230231
.enumerate()
231232
.find_map(|(i, s)| {
232-
// TODO: Error handling
233-
(&middleware::Statement::try_from(s.clone()).unwrap() == op_arg).then_some(i)
233+
(&middleware::Statement::try_from(s.clone()).ok()? == op_arg).then_some(i)
234234
})
235235
.map(OperationArg::Index)
236-
.ok_or(OperationArgError::StatementNotFound),
236+
.ok_or(anyhow!("statement not found")),
237237
}
238238
}
239239

240240
fn process_private_statements_operations(
241241
params: &Params,
242242
statements: &[Statement],
243243
input_operations: &[middleware::Operation],
244-
) -> Result<Vec<Operation>, OperationArgError> {
244+
) -> Result<Vec<Operation>> {
245245
let mut operations = Vec::new();
246246
for i in 0..params.max_priv_statements() {
247247
let op = input_operations
@@ -252,7 +252,7 @@ impl MockMainPod {
252252
let mut args = mid_args
253253
.iter()
254254
.map(|mid_arg| Self::find_op_arg(statements, mid_arg))
255-
.collect::<Result<Vec<_>, OperationArgError>>()?;
255+
.collect::<Result<Vec<_>>>()?;
256256
Self::pad_operation_args(params, &mut args);
257257
operations.push(Operation(op.code(), args));
258258
}
@@ -265,7 +265,7 @@ impl MockMainPod {
265265
params: &Params,
266266
statements: &[Statement],
267267
mut operations: Vec<Operation>,
268-
) -> Result<Vec<Operation>, OperationArgError> {
268+
) -> Result<Vec<Operation>> {
269269
let offset_public_statements = statements.len() - params.max_public_statements;
270270
operations.push(Operation(NativeOperation::NewEntry, vec![]));
271271
for i in 0..(params.max_public_statements - 1) {
@@ -318,7 +318,7 @@ impl MockMainPod {
318318
statements[statements.len() - params.max_public_statements..].to_vec();
319319

320320
// get the id out of the public statements
321-
let id: PodId = PodId(hash_statements(&public_statements)?);
321+
let id: PodId = PodId(hash_statements(&public_statements));
322322

323323
Ok(Self {
324324
params: params.clone(),
@@ -335,7 +335,7 @@ impl MockMainPod {
335335
fn statement_none(params: &Params) -> Statement {
336336
let mut args = Vec::with_capacity(params.max_statement_args);
337337
Self::pad_statement_args(&params, &mut args);
338-
Statement(NativeStatement::None, args)
338+
Statement(NativePredicate::None, args)
339339
}
340340

341341
fn operation_none(params: &Params) -> Operation {
@@ -353,12 +353,12 @@ impl MockMainPod {
353353
}
354354
}
355355

356-
pub fn hash_statements(statements: &[Statement]) -> Result<middleware::Hash> {
356+
pub fn hash_statements(statements: &[Statement]) -> middleware::Hash {
357357
let field_elems = statements
358358
.into_iter()
359359
.flat_map(|statement| statement.clone().to_fields().0)
360360
.collect::<Vec<_>>();
361-
Ok(Hash(PoseidonHash::hash_no_pad(&field_elems).elements))
361+
Hash(PoseidonHash::hash_no_pad(&field_elems).elements)
362362
}
363363

364364
impl Pod for MockMainPod {
@@ -367,14 +367,14 @@ impl Pod for MockMainPod {
367367
// get the input_statements from the self.statements
368368
let input_statements = &self.statements[input_statement_offset..];
369369
// get the id out of the public statements, and ensure it is equal to self.id
370-
let ids_match = self.id == PodId(hash_statements(&self.public_statements).unwrap());
370+
let ids_match = self.id == PodId(hash_statements(&self.public_statements));
371371
// find a ValueOf statement from the public statements with key=KEY_TYPE and check that the
372372
// value is PodType::MockMainPod
373373
let has_type_statement = self
374374
.public_statements
375375
.iter()
376376
.find(|s| {
377-
s.0 == NativeStatement::ValueOf
377+
s.0 == NativePredicate::ValueOf
378378
&& s.1.len() > 0
379379
&& if let StatementArg::Key(AnchoredKey(pod_id, key_hash)) = s.1[0] {
380380
pod_id == SELF && key_hash == hash_str(KEY_TYPE)
@@ -402,7 +402,7 @@ impl Pod for MockMainPod {
402402
s,
403403
)
404404
})
405-
.filter(|(_, s)| s.0 == NativeStatement::ValueOf)
405+
.filter(|(_, s)| s.0 == NativePredicate::ValueOf)
406406
.flat_map(|(i, s)| {
407407
if let StatementArg::Key(ak) = &s.1[0] {
408408
vec![(i, ak.1, ak.0)]
@@ -473,37 +473,38 @@ pub mod tests {
473473
use crate::middleware;
474474

475475
#[test]
476-
fn test_mock_main_zu_kyc() {
476+
fn test_mock_main_zu_kyc() -> Result<()> {
477477
let params = middleware::Params::default();
478478

479479
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(&params);
480480
let mut signer = MockSigner {
481481
pk: "ZooGov".into(),
482482
};
483-
let gov_id_pod = gov_id_builder.sign(&mut signer).unwrap();
483+
let gov_id_pod = gov_id_builder.sign(&mut signer)?;
484484
let mut signer = MockSigner {
485485
pk: "ZooDeel".into(),
486486
};
487-
let pay_stub_pod = pay_stub_builder.sign(&mut signer).unwrap();
487+
let pay_stub_pod = pay_stub_builder.sign(&mut signer)?;
488488
let kyc_builder = zu_kyc_pod_builder(&params, &gov_id_pod, &pay_stub_pod);
489489

490490
let mut prover = MockProver {};
491-
let kyc_pod = kyc_builder.prove(&mut prover).unwrap();
491+
let kyc_pod = kyc_builder.prove(&mut prover)?;
492492
let pod = kyc_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
493493

494494
println!("{:#}", pod);
495495

496496
assert_eq!(pod.verify(), true); // TODO
497497
// println!("id: {}", pod.id());
498498
// println!("pub_statements: {:?}", pod.pub_statements());
499+
Ok(())
499500
}
500501

501502
#[test]
502-
fn test_mock_main_great_boy() {
503+
fn test_mock_main_great_boy() -> Result<()> {
503504
let great_boy_builder = great_boy_pod_full_flow();
504505

505506
let mut prover = MockProver {};
506-
let great_boy_pod = great_boy_builder.prove(&mut prover).unwrap();
507+
let great_boy_pod = great_boy_builder.prove(&mut prover)?;
507508
let pod = great_boy_pod
508509
.pod
509510
.into_any()
@@ -513,16 +514,20 @@ pub mod tests {
513514
println!("{}", pod);
514515

515516
assert_eq!(pod.verify(), true);
517+
518+
Ok(())
516519
}
517520

518521
#[test]
519-
fn test_mock_main_tickets() {
522+
fn test_mock_main_tickets() -> Result<()> {
520523
let tickets_builder = tickets_pod_full_flow();
521524
let mut prover = MockProver {};
522-
let proof_pod = tickets_builder.prove(&mut prover).unwrap();
525+
let proof_pod = tickets_builder.prove(&mut prover)?;
523526
let pod = proof_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
524527

525528
println!("{}", pod);
526529
assert_eq!(pod.verify(), true);
530+
531+
Ok(())
527532
}
528533
}

src/backends/mock_main/operation.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
use std::fmt;
2-
31
use anyhow::Result;
4-
5-
use crate::middleware::{self, NativeOperation};
2+
use std::fmt;
63

74
use super::Statement;
5+
use crate::middleware::{self, NativeOperation};
86

97
#[derive(Clone, Debug, PartialEq, Eq)]
108
pub enum OperationArg {
@@ -18,23 +16,6 @@ impl OperationArg {
1816
}
1917
}
2018

21-
#[derive(Clone, Debug, PartialEq, Eq)]
22-
pub enum OperationArgError {
23-
KeyNotFound,
24-
StatementNotFound,
25-
}
26-
27-
impl std::fmt::Display for OperationArgError {
28-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29-
match self {
30-
OperationArgError::KeyNotFound => write!(f, "Key not found"),
31-
OperationArgError::StatementNotFound => write!(f, "Statement not found"),
32-
}
33-
}
34-
}
35-
36-
impl std::error::Error for OperationArgError {}
37-
3819
#[derive(Clone, Debug, PartialEq, Eq)]
3920
pub struct Operation(pub NativeOperation, pub Vec<OperationArg>);
4021

src/backends/mock_main/statement.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
use std::fmt;
2-
31
use anyhow::{anyhow, Result};
2+
use std::fmt;
43

5-
use crate::middleware::{self, NativeStatement, StatementArg, ToFields};
4+
use crate::middleware::{self, NativePredicate, StatementArg, ToFields};
65

76
#[derive(Clone, Debug, PartialEq, Eq)]
8-
pub struct Statement(pub NativeStatement, pub Vec<StatementArg>);
7+
pub struct Statement(pub NativePredicate, pub Vec<StatementArg>);
98

109
impl Statement {
1110
pub fn is_none(&self) -> bool {
12-
self.0 == NativeStatement::None
11+
self.0 == NativePredicate::None
1312
}
1413
/// Argument method. Trailing Nones are filtered out.
1514
pub fn args(&self) -> Vec<StatementArg> {
@@ -44,7 +43,7 @@ impl TryFrom<Statement> for middleware::Statement {
4443
type Error = anyhow::Error;
4544
fn try_from(s: Statement) -> Result<Self> {
4645
type S = middleware::Statement;
47-
type NS = NativeStatement;
46+
type NP = NativePredicate;
4847
type SA = StatementArg;
4948
let proper_args = s.args();
5049
let args = (
@@ -53,27 +52,27 @@ impl TryFrom<Statement> for middleware::Statement {
5352
proper_args.get(2).cloned(),
5453
);
5554
Ok(match (s.0, args, proper_args.len()) {
56-
(NS::None, _, 0) => S::None,
57-
(NS::ValueOf, (Some(SA::Key(ak)), Some(SA::Literal(v)), None), 2) => S::ValueOf(ak, v),
58-
(NS::Equal, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Equal(ak1, ak2),
59-
(NS::NotEqual, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
55+
(NP::None, _, 0) => S::None,
56+
(NP::ValueOf, (Some(SA::Key(ak)), Some(SA::Literal(v)), None), 2) => S::ValueOf(ak, v),
57+
(NP::Equal, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Equal(ak1, ak2),
58+
(NP::NotEqual, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
6059
S::NotEqual(ak1, ak2)
6160
}
62-
(NS::Gt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Gt(ak1, ak2),
63-
(NS::Lt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Lt(ak1, ak2),
64-
(NS::Contains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
61+
(NP::Gt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Gt(ak1, ak2),
62+
(NP::Lt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Lt(ak1, ak2),
63+
(NP::Contains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
6564
S::Contains(ak1, ak2)
6665
}
67-
(NS::NotContains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
66+
(NP::NotContains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
6867
S::NotContains(ak1, ak2)
6968
}
70-
(NS::SumOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
69+
(NP::SumOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
7170
S::SumOf(ak1, ak2, ak3)
7271
}
73-
(NS::ProductOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
72+
(NP::ProductOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
7473
S::ProductOf(ak1, ak2, ak3)
7574
}
76-
(NS::MaxOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
75+
(NP::MaxOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
7776
S::MaxOf(ak1, ak2, ak3)
7877
}
7978
_ => Err(anyhow!("Ill-formed statement expression {:?}", s))?,

src/backends/mock_signed.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
use anyhow::Result;
2+
use std::any::Any;
3+
use std::collections::HashMap;
4+
15
use crate::middleware::{
26
containers::Dictionary, hash_str, AnchoredKey, Hash, Params, Pod, PodId, PodSigner, PodType,
37
Statement, Value, KEY_SIGNER, KEY_TYPE,
48
};
59
use crate::primitives::merkletree::MerkleTree;
6-
use anyhow::Result;
7-
use std::any::Any;
8-
use std::collections::HashMap;
910

1011
pub struct MockSigner {
1112
pub pk: String,

0 commit comments

Comments
 (0)