Fe contains (#145)

* Contains should take three arguments (root, key, value)

* Add a test for frontend Dictionaries

* Separate frontend and middleware operations

* Make tests pass: add arg to contains

* Cargo fmt

* Merkleproof verify circuit (#143)

* merkletree: add keypath circuit

* merkletree-circuit: implement proof of existence verification in-circuit

* parametrize max_depth at the tree circuit

* Constrain selectors in-circuit

* implement merketree nonexistence proof circuit, and add edgecase tests

* add non-existence proofs documentation in the mdbook, mv EMPTY->EMPTY_VALUE & NULL->EMPTY_HASH, dependency clean and public exposure methods

* review comments, some extra polishing and add a test that expects wrong proofs to fail

* Add circuit to check only merkleproofs-of-existence

With this, the merkletree_circuit module offers two different circuits:
- `MerkleProofCircuit`: allows to verify both proofs of existence and proofs
non-existence with the same circuit.
- `MerkleProofExistenceCircuit`: allows to verify proofs of existence only.

In this way, if only proofs of existence are needed,
`MerkleProofExistenceCircuit` should be used, which requires less amount
of constraints than `MerkleProofCircuit`.

* Code review

---------

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

* Towards Contains/NotContains in middleware and backend

* Fix build

* Adding error handling to deal with op compile introduce extra ops

* Incorporate Merkle proofs into MockMainPod

* Merkleproof verify circuit (#143)

* merkletree: add keypath circuit

* merkletree-circuit: implement proof of existence verification in-circuit

* parametrize max_depth at the tree circuit

* Constrain selectors in-circuit

* implement merketree nonexistence proof circuit, and add edgecase tests

* add non-existence proofs documentation in the mdbook, mv EMPTY->EMPTY_VALUE & NULL->EMPTY_HASH, dependency clean and public exposure methods

* review comments, some extra polishing and add a test that expects wrong proofs to fail

* Add circuit to check only merkleproofs-of-existence

With this, the merkletree_circuit module offers two different circuits:
- `MerkleProofCircuit`: allows to verify both proofs of existence and proofs
non-existence with the same circuit.
- `MerkleProofExistenceCircuit`: allows to verify proofs of existence only.

In this way, if only proofs of existence are needed,
`MerkleProofExistenceCircuit` should be used, which requires less amount
of constraints than `MerkleProofCircuit`.

* Code review

---------

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

* Towards Contains/NotContains in middleware and backend

* Frontend compound types -- allow one frontend operation to produce multiple middleware statements (in progress)

* Incorporate Merkle proofs into MockMainPod

* Incorporate Merkle proof op arg into frontend

* Compile one statement to many, in progress

* Fix remaining tests

* Minor clean-up

* Oops I did a bunch of work in the middle of a rebase, committing

* Incorporate Merkle proof op arg into frontend

* still working on frontend compound types, refactor compile() to output multiple statements

* Contains statements for frontend types: code compiles

* Tests pass

* Examples use front-end compound types

* Remove old Contains and NotContains from frontend

* Add nin to typos

* Code review

---------

Co-authored-by: arnaucube <git@arnaucube.com>
Co-authored-by: Ahmad <root@ahmadafuni.com>
This commit is contained in:
tideofwords 2025-03-26 17:54:58 -07:00 committed by GitHub
parent d6033b7090
commit d00ff95f41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 789 additions and 162 deletions

View file

@ -44,8 +44,12 @@ pub enum Statement {
NotEqual(AnchoredKey, AnchoredKey),
Gt(AnchoredKey, AnchoredKey),
Lt(AnchoredKey, AnchoredKey),
Contains(AnchoredKey, AnchoredKey),
NotContains(AnchoredKey, AnchoredKey),
Contains(
/* root */ AnchoredKey,
/* key */ AnchoredKey,
/* value */ AnchoredKey,
),
NotContains(/* root */ AnchoredKey, /* key */ AnchoredKey),
SumOf(AnchoredKey, AnchoredKey, AnchoredKey),
ProductOf(AnchoredKey, AnchoredKey, AnchoredKey),
MaxOf(AnchoredKey, AnchoredKey, AnchoredKey),
@ -65,7 +69,7 @@ impl Statement {
Self::NotEqual(_, _) => Native(NativePredicate::NotEqual),
Self::Gt(_, _) => Native(NativePredicate::Gt),
Self::Lt(_, _) => Native(NativePredicate::Lt),
Self::Contains(_, _) => Native(NativePredicate::Contains),
Self::Contains(_, _, _) => Native(NativePredicate::Contains),
Self::NotContains(_, _) => Native(NativePredicate::NotContains),
Self::SumOf(_, _, _) => Native(NativePredicate::SumOf),
Self::ProductOf(_, _, _) => Native(NativePredicate::ProductOf),
@ -82,7 +86,7 @@ impl Statement {
Self::NotEqual(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Gt(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Lt(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Contains(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Contains(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
Self::NotContains(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::SumOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
Self::ProductOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
@ -130,8 +134,10 @@ impl Statement {
}
}
Native(NativePredicate::Contains) => {
if let (StatementArg::Key(a0), StatementArg::Key(a1)) = (args[0], args[1]) {
Ok(Self::Contains(a0, a1))
if let (StatementArg::Key(a0), StatementArg::Key(a1), StatementArg::Key(a2)) =
(args[0], args[1], args[2])
{
Ok(Self::Contains(a0, a1, a2))
} else {
Err(anyhow!("Incorrect statement args"))
}