Skip to content

Commit d7d704f

Browse files
committed
Towards Contains/NotContains in middleware and backend
1 parent ad791f1 commit d7d704f

File tree

5 files changed

+145
-65
lines changed

5 files changed

+145
-65
lines changed

src/backends/plonky2/mock_main/mod.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,21 +222,24 @@ impl MockMainPod {
222222

223223
fn find_op_arg(
224224
statements: &[Statement],
225-
op_arg: &middleware::Statement,
225+
op_arg: &middleware::OperationArg,
226226
) -> Result<OperationArg> {
227227
match op_arg {
228-
middleware::Statement::None => Ok(OperationArg::None),
229-
_ => statements
230-
.iter()
231-
.enumerate()
232-
.find_map(|(i, s)| {
233-
(&middleware::Statement::try_from(s.clone()).ok()? == op_arg).then_some(i)
234-
})
235-
.map(OperationArg::Index)
236-
.ok_or(anyhow!(
237-
"Statement corresponding to op arg {} not found",
238-
op_arg
239-
)),
228+
middleware::OperationArg::Statement(s_arg) => match s_arg {
229+
middleware::Statement::None => Ok(OperationArg::None),
230+
_ => statements
231+
.iter()
232+
.enumerate()
233+
.find_map(|(i, s)| {
234+
(&middleware::Statement::try_from(s.clone()).ok()? == s_arg).then_some(i)
235+
})
236+
.map(OperationArg::Index)
237+
.ok_or(anyhow!(
238+
"Statement corresponding to op arg {} not found",
239+
op_arg
240+
)),
241+
},
242+
_ => todo!(),
240243
}
241244
}
242245

@@ -285,7 +288,10 @@ impl MockMainPod {
285288
Operation(
286289
OperationType::Native(NativeOperation::CopyStatement),
287290
// TODO
288-
vec![Self::find_op_arg(statements, &mid_arg.try_into().unwrap())?],
291+
vec![Self::find_op_arg(
292+
statements,
293+
&middleware::OperationArg::Statement(mid_arg.try_into().unwrap()),
294+
)?],
289295
)
290296
};
291297
fill_pad(&mut op.1, OperationArg::None, params.max_operation_args);

src/backends/plonky2/mock_main/operation.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ use anyhow::Result;
22
use std::fmt;
33

44
use super::Statement;
5-
use crate::middleware::{self, OperationType};
5+
use crate::{
6+
backends::plonky2::primitives::merkletree::MerkleProof,
7+
middleware::{self, OperationType},
8+
};
69

710
#[derive(Clone, Debug, PartialEq, Eq)]
811
pub enum OperationArg {
912
None,
1013
Index(usize),
14+
// TODO: Replace with `MerkleProofIndex`.
15+
MerkleProof(MerkleProof),
1116
}
1217

1318
impl OperationArg {
@@ -26,9 +31,17 @@ impl Operation {
2631
.iter()
2732
.flat_map(|arg| match arg {
2833
OperationArg::None => None,
29-
OperationArg::Index(i) => Some(statements[*i].clone().try_into()),
34+
OperationArg::Index(i) => Some(
35+
statements[*i]
36+
.clone()
37+
.try_into()
38+
.map(|s| crate::middleware::OperationArg::Statement(s)),
39+
),
40+
OperationArg::MerkleProof(pf) => {
41+
Some(Ok(crate::middleware::OperationArg::MerkleProof(pf.clone())))
42+
}
3043
})
31-
.collect::<Result<Vec<crate::middleware::Statement>>>()?;
44+
.collect::<Result<Vec<_>>>()?;
3245
middleware::Operation::op(self.0.clone(), &deref_args)
3346
}
3447
}
@@ -44,6 +57,7 @@ impl fmt::Display for Operation {
4457
match arg {
4558
OperationArg::None => write!(f, "none")?,
4659
OperationArg::Index(i) => write!(f, "{:02}", i)?,
60+
OperationArg::MerkleProof(pf) => write!(f, "{}", pf)?,
4761
}
4862
}
4963
}

src/backends/plonky2/primitives/merkletree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl fmt::Display for MerkleTree {
207207
}
208208
}
209209

210-
#[derive(Clone, Debug)]
210+
#[derive(Clone, Debug, PartialEq, Eq)]
211211
pub struct MerkleProof {
212212
// note: currently we don't use the `_existence` field, we would use if we merge the methods
213213
// `verify` and `verify_nonexistence` into a single one

src/middleware/operation.rs

Lines changed: 101 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,33 @@ use std::fmt;
33
use anyhow::{anyhow, Result};
44

55
use super::{CustomPredicateRef, NativePredicate, Statement, StatementArg};
6-
use crate::middleware::{AnchoredKey, Params, Predicate, Value, SELF};
6+
use crate::{
7+
backends::plonky2::primitives::merkletree::{MerkleProof, MerkleTree},
8+
middleware::{AnchoredKey, Params, Predicate, Value, SELF},
9+
};
710

811
#[derive(Clone, Debug, PartialEq, Eq)]
912
pub enum OperationType {
1013
Native(NativeOperation),
1114
Custom(CustomPredicateRef),
1215
}
1316

17+
#[derive(Clone, Debug, PartialEq, Eq)]
18+
pub enum OperationArg {
19+
Statement(Statement),
20+
MerkleProof(MerkleProof),
21+
}
22+
23+
impl fmt::Display for OperationArg {
24+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25+
match self {
26+
Self::Statement(s) => write!(f, "{}", s)?,
27+
Self::MerkleProof(pf) => write!(f, "merkle_proof({})", pf)?,
28+
}
29+
Ok(())
30+
}
31+
}
32+
1433
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1534
pub enum NativeOperation {
1635
None = 0,
@@ -81,8 +100,17 @@ pub enum Operation {
81100
TransitiveEqualFromStatements(Statement, Statement),
82101
GtToNotEqual(Statement),
83102
LtToNotEqual(Statement),
84-
ContainsFromEntries(Statement, Statement, Statement),
85-
NotContainsFromEntries(Statement, Statement),
103+
ContainsFromEntries(
104+
/* root */ Statement,
105+
/* key */ Statement,
106+
/* value */ Statement,
107+
/* proof */ MerkleProof,
108+
),
109+
NotContainsFromEntries(
110+
/* root */ Statement,
111+
/* key */ Statement,
112+
/* proof */ MerkleProof,
113+
),
86114
SumOf(Statement, Statement, Statement),
87115
ProductOf(Statement, Statement, Statement),
88116
MaxOf(Statement, Statement, Statement),
@@ -104,72 +132,95 @@ impl Operation {
104132
Self::TransitiveEqualFromStatements(_, _) => OT::Native(TransitiveEqualFromStatements),
105133
Self::GtToNotEqual(_) => OT::Native(GtToNotEqual),
106134
Self::LtToNotEqual(_) => OT::Native(LtToNotEqual),
107-
Self::ContainsFromEntries(_, _, _) => OT::Native(ContainsFromEntries),
108-
Self::NotContainsFromEntries(_, _) => OT::Native(NotContainsFromEntries),
135+
Self::ContainsFromEntries(_, _, _, _) => OT::Native(ContainsFromEntries),
136+
Self::NotContainsFromEntries(_, _, _) => OT::Native(NotContainsFromEntries),
109137
Self::SumOf(_, _, _) => OT::Native(SumOf),
110138
Self::ProductOf(_, _, _) => OT::Native(ProductOf),
111139
Self::MaxOf(_, _, _) => OT::Native(MaxOf),
112140
Self::Custom(cpr, _) => OT::Custom(cpr.clone()),
113141
}
114142
}
115143

116-
pub fn args(&self) -> Vec<Statement> {
144+
pub fn args(&self) -> Vec<OperationArg> {
145+
use OperationArg::{MerkleProof as MP, Statement as S};
117146
match self.clone() {
118147
Self::None => vec![],
119148
Self::NewEntry => vec![],
120-
Self::CopyStatement(s) => vec![s],
121-
Self::EqualFromEntries(s1, s2) => vec![s1, s2],
122-
Self::NotEqualFromEntries(s1, s2) => vec![s1, s2],
123-
Self::GtFromEntries(s1, s2) => vec![s1, s2],
124-
Self::LtFromEntries(s1, s2) => vec![s1, s2],
125-
Self::TransitiveEqualFromStatements(s1, s2) => vec![s1, s2],
126-
Self::GtToNotEqual(s) => vec![s],
127-
Self::LtToNotEqual(s) => vec![s],
128-
Self::ContainsFromEntries(s1, s2, s3) => vec![s1, s2, s3],
129-
Self::NotContainsFromEntries(s1, s2) => vec![s1, s2],
130-
Self::SumOf(s1, s2, s3) => vec![s1, s2, s3],
131-
Self::ProductOf(s1, s2, s3) => vec![s1, s2, s3],
132-
Self::MaxOf(s1, s2, s3) => vec![s1, s2, s3],
133-
Self::Custom(_, args) => args,
149+
Self::CopyStatement(s) => vec![S(s)],
150+
Self::EqualFromEntries(s1, s2) => vec![S(s1), S(s2)],
151+
Self::NotEqualFromEntries(s1, s2) => vec![S(s1), S(s2)],
152+
Self::GtFromEntries(s1, s2) => vec![S(s1), S(s2)],
153+
Self::LtFromEntries(s1, s2) => vec![S(s1), S(s2)],
154+
Self::TransitiveEqualFromStatements(s1, s2) => vec![S(s1), S(s2)],
155+
Self::GtToNotEqual(s) => vec![S(s)],
156+
Self::LtToNotEqual(s) => vec![S(s)],
157+
Self::ContainsFromEntries(s1, s2, s3, pf) => vec![S(s1), S(s2), S(s3), MP(pf)],
158+
Self::NotContainsFromEntries(s1, s2, pf) => vec![S(s1), S(s2), MP(pf)],
159+
Self::SumOf(s1, s2, s3) => vec![S(s1), S(s2), S(s3)],
160+
Self::ProductOf(s1, s2, s3) => vec![S(s1), S(s2), S(s3)],
161+
Self::MaxOf(s1, s2, s3) => vec![S(s1), S(s2), S(s3)],
162+
Self::Custom(_, args) => args.into_iter().map(|s| S(s)).collect(),
134163
}
135164
}
136165
/// Forms operation from op-code and arguments.
137-
pub fn op(op_code: OperationType, args: &[Statement]) -> Result<Self> {
166+
pub fn op(op_code: OperationType, args: &[OperationArg]) -> Result<Self> {
167+
use OperationArg::{MerkleProof as MP, Statement as S};
138168
type NO = NativeOperation;
139169
let arg_tup = (
140170
args.first().cloned(),
141171
args.get(1).cloned(),
142172
args.get(2).cloned(),
173+
args.get(3).cloned(),
143174
);
144175
Ok(match op_code {
145176
OperationType::Native(o) => match (o, arg_tup, args.len()) {
146-
(NO::None, (None, None, None), 0) => Self::None,
147-
(NO::NewEntry, (None, None, None), 0) => Self::NewEntry,
148-
(NO::CopyStatement, (Some(s), None, None), 1) => Self::CopyStatement(s),
149-
(NO::EqualFromEntries, (Some(s1), Some(s2), None), 2) => {
177+
(NO::None, (None, None, None, None), 0) => Self::None,
178+
(NO::NewEntry, (None, None, None, None), 0) => Self::NewEntry,
179+
(NO::CopyStatement, (Some(S(s)), None, None, None), 1) => Self::CopyStatement(s),
180+
(NO::EqualFromEntries, (Some(S(s1)), Some(S(s2)), None, None), 2) => {
150181
Self::EqualFromEntries(s1, s2)
151182
}
152-
(NO::NotEqualFromEntries, (Some(s1), Some(s2), None), 2) => {
183+
(NO::NotEqualFromEntries, (Some(S(s1)), Some(S(s2)), None, None), 2) => {
153184
Self::NotEqualFromEntries(s1, s2)
154185
}
155-
(NO::GtFromEntries, (Some(s1), Some(s2), None), 2) => Self::GtFromEntries(s1, s2),
156-
(NO::LtFromEntries, (Some(s1), Some(s2), None), 2) => Self::LtFromEntries(s1, s2),
157-
(NO::ContainsFromEntries, (Some(s1), Some(s2), Some(s3)), 3) => {
158-
Self::ContainsFromEntries(s1, s2, s3)
186+
(NO::GtFromEntries, (Some(S(s1)), Some(S(s2)), None, None), 2) => {
187+
Self::GtFromEntries(s1, s2)
188+
}
189+
(NO::LtFromEntries, (Some(S(s1)), Some(S(s2)), None, None), 2) => {
190+
Self::LtFromEntries(s1, s2)
191+
}
192+
(
193+
NO::ContainsFromEntries,
194+
(Some(S(s1)), Some(S(s2)), Some(S(s3)), Some(MP(pf))),
195+
4,
196+
) => Self::ContainsFromEntries(s1, s2, s3, pf),
197+
(NO::NotContainsFromEntries, (Some(S(s1)), Some(S(s2)), Some(MP(pf)), None), 3) => {
198+
Self::NotContainsFromEntries(s1, s2, pf)
199+
}
200+
(NO::SumOf, (Some(S(s1)), Some(S(s2)), Some(S(s3)), None), 3) => {
201+
Self::SumOf(s1, s2, s3)
159202
}
160-
(NO::NotContainsFromEntries, (Some(s1), Some(s2), None), 2) => {
161-
Self::NotContainsFromEntries(s1, s2)
203+
(NO::ProductOf, (Some(S(s1)), Some(S(s2)), Some(S(s3)), None), 3) => {
204+
Self::ProductOf(s1, s2, s3)
205+
}
206+
(NO::MaxOf, (Some(S(s1)), Some(S(s2)), Some(S(s3)), None), 3) => {
207+
Self::MaxOf(s1, s2, s3)
162208
}
163-
(NO::SumOf, (Some(s1), Some(s2), Some(s3)), 3) => Self::SumOf(s1, s2, s3),
164-
(NO::ProductOf, (Some(s1), Some(s2), Some(s3)), 3) => Self::ProductOf(s1, s2, s3),
165-
(NO::MaxOf, (Some(s1), Some(s2), Some(s3)), 3) => Self::MaxOf(s1, s2, s3),
166209
_ => Err(anyhow!(
167210
"Ill-formed operation {:?} with arguments {:?}.",
168211
op_code,
169212
args
170213
))?,
171214
},
172-
OperationType::Custom(cpr) => Self::Custom(cpr, args.to_vec()),
215+
OperationType::Custom(cpr) => Self::Custom(
216+
cpr,
217+
args.iter()
218+
.map(|a| match a {
219+
S(s) => Ok(s.clone()),
220+
_ => Err(anyhow!("Invalid argument to custom operation: {:?}", a)),
221+
})
222+
.collect::<Result<Vec<_>>>()?,
223+
),
173224
})
174225
}
175226
/// Gives the output statement of the given operation, where determined
@@ -245,20 +296,25 @@ impl Operation {
245296
Self::LtToNotEqual(_) => {
246297
return Err(anyhow!("Invalid operation"));
247298
}
248-
Self::ContainsFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3)) =>
249-
/* TODO */
299+
Self::ContainsFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3), pf)
300+
if MerkleTree::verify(pf.siblings.len(), (*v1).into(), &pf, v2, v3)? == () =>
250301
{
251-
Some(vec![StatementArg::Key(*ak1), StatementArg::Key(*ak2)])
302+
Some(vec![
303+
StatementArg::Key(*ak1),
304+
StatementArg::Key(*ak2),
305+
StatementArg::Key(*ak3),
306+
])
252307
}
253-
Self::ContainsFromEntries(_, _, _) => {
308+
Self::ContainsFromEntries(_, _, _, _) => {
254309
return Err(anyhow!("Invalid operation"));
255310
}
256-
Self::NotContainsFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2)) =>
257-
/* TODO */
311+
Self::NotContainsFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2), pf)
312+
if MerkleTree::verify_nonexistence(pf.siblings.len(), (*v1).into(), &pf, v2)?
313+
== () =>
258314
{
259315
Some(vec![StatementArg::Key(*ak1), StatementArg::Key(*ak2)])
260316
}
261-
Self::NotContainsFromEntries(_, _) => {
317+
Self::NotContainsFromEntries(_, _, _) => {
262318
return Err(anyhow!("Invalid operation"));
263319
}
264320
Self::SumOf(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3)) => {
@@ -327,12 +383,12 @@ impl Operation {
327383
(Self::LtFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2)), Lt(ak3, ak4)) => {
328384
Ok(v1 < v2 && ak3 == ak1 && ak4 == ak2)
329385
}
330-
(Self::ContainsFromEntries(_, _, _), Contains(_, _, _)) =>
386+
(Self::ContainsFromEntries(_, _, _, _), Contains(_, _, _)) =>
331387
/* TODO */
332388
{
333389
Ok(true)
334390
}
335-
(Self::NotContainsFromEntries(_, _), NotContains(_, _)) =>
391+
(Self::NotContainsFromEntries(_, _, _), NotContains(_, _)) =>
336392
/* TODO */
337393
{
338394
Ok(true)

src/middleware/statement.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ pub enum Statement {
3939
NotEqual(AnchoredKey, AnchoredKey),
4040
Gt(AnchoredKey, AnchoredKey),
4141
Lt(AnchoredKey, AnchoredKey),
42-
Contains(AnchoredKey, AnchoredKey, AnchoredKey),
43-
NotContains(AnchoredKey, AnchoredKey),
42+
Contains(
43+
/* root */ AnchoredKey,
44+
/* key */ AnchoredKey,
45+
/* value */ AnchoredKey,
46+
),
47+
NotContains(/* root */ AnchoredKey, /* key */ AnchoredKey),
4448
SumOf(AnchoredKey, AnchoredKey, AnchoredKey),
4549
ProductOf(AnchoredKey, AnchoredKey, AnchoredKey),
4650
MaxOf(AnchoredKey, AnchoredKey, AnchoredKey),

0 commit comments

Comments
 (0)