-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add POD uniqueness module #1884
Changes from 1 commit
7ddf10f
b3722e5
24c37da
50e4ffe
cfa1f33
5daa712
2117cec
9b7aafe
0ab9d5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,26 +19,26 @@ template UniquenessModule( | |
signal output valuesAreUnique; | ||
|
||
// Array of field elements indicating whether the corresponding | ||
ax0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// element of `values` is unique, i.e. isUnique[i] = 0 iff | ||
// values[i] is not unique. | ||
signal isUnique[NUM_LIST_ELEMENTS]; | ||
// element of `values` has no duplicates following it in `values`, | ||
// i.e. noDupsAfter[i] = 0 iff this is the case. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be |
||
signal noDupsAfter[NUM_LIST_ELEMENTS]; | ||
|
||
// Loop through and check whether the ith element of `values` is | ||
// not an element of `values` with the first i+1 elements removed. | ||
for(var i = 0; i < NUM_LIST_ELEMENTS; i++) { | ||
var j = i+1; | ||
isUnique[i] <== | ||
UnnormalisedListNonMembership(NUM_LIST_ELEMENTS - j, NUM_LIST_ELEMENTS)( | ||
noDupsAfter[i] <== | ||
NotEqualsAny(NUM_LIST_ELEMENTS - j, NUM_LIST_ELEMENTS)( | ||
values[i], | ||
Rotl(j, NUM_LIST_ELEMENTS)(values) | ||
ArrayRotl(j, NUM_LIST_ELEMENTS)(values) | ||
); | ||
} | ||
|
||
// All values are unique iff all elements of `isUnique` are non-zero. | ||
// All values are unique iff all elements of `noDupsAfter` are non-zero. | ||
valuesAreUnique <== NOT()( | ||
IsZero()( | ||
MultiAND(NUM_LIST_ELEMENTS)( | ||
ax0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
isUnique | ||
noDupsAfter | ||
) | ||
) | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -205,6 +205,11 @@ export function zeroResidueMod(x: CircuitSignal, n: bigint): bigint { | |
* Creates dummy signals for unused object slots in ProtoPODGPC via dummy | ||
ax0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* content IDs in the form of POD string hashes of the message `unused POD ${n}` | ||
* as well as corresponding signatures. | ||
* | ||
* Note that these do not arise from actual PODs but they present valid content | ||
* IDs since they will pass the necessary signature checks in the | ||
* ProtoPODGPC. This is sufficient because they do not have any entries | ||
* associated with them. | ||
*/ | ||
export function dummyObjectSignals( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we ever care enough about performance, we could pre-calculate several of these and store them in a static array. |
||
numObjects: number | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems out-of-place for this as a general list-non-membership template. The need to take only the head of the list is motivated only by the uniqueness use case, so maybe Take should happen at that level, on the input array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how I initially did it, but Circom doesn't like that approach:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where's the unknown size? I'd expect all the array lenghts to be known (based on template args) at the point of use. I'd have to see the specific code to comment on it, though, and I'm fully willing to believe that circom is broken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the array sizes depend only on the template parameter and loop index. I assume there is a bug in the loop + anonymous component unrolling code. What I did was replace the list non-membership and uniqueness module templates with the following:
My original version used
Drop
instead ofTake
andRotl
(which is what I believe you suggested in your other comment) but yielded the same result.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. Seems like a circom limitation keeps us from sizing arrays based on loop variables, but not if they're inside of templates. It's unintuitive to me that a loop variable can be a template argument (as demonstrated in our use of Take and Rotl) but can't be an array size. Take does return an array of a size which depends on its template argument, so it shouldn't matter if it's directly in the loop or in a template instantiated in the loop.
Would it help if you combined Take and Rotl into a single Slice template which returned array elements from [I, I+N)? Or would that make the situation worse? I don't really understand what circom's limitation is, so it's hard to know what to suggest. If there's no obvious solution I'm okay with accepting what works, given the final number of constraints is the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried doing this with a single
drop
-like template but ran into the same error, which is what led me to the current approach.